diff options
| author | Michael Merickel <michael@merickel.org> | 2018-10-15 01:55:54 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2018-10-15 09:24:07 -0500 |
| commit | 0c29cf2df41600d3906d521c72991c7686018b71 (patch) | |
| tree | ff907f90ec9467e12874c9b2c961549d0e7caf74 | |
| parent | 851c368e3c158e264358de10446f5b5de240e534 (diff) | |
| download | pyramid-0c29cf2df41600d3906d521c72991c7686018b71.tar.gz pyramid-0c29cf2df41600d3906d521c72991c7686018b71.tar.bz2 pyramid-0c29cf2df41600d3906d521c72991c7686018b71.zip | |
format source using black
177 files changed, 13381 insertions, 7013 deletions
@@ -55,46 +55,47 @@ testing_extras = tests_require + [ 'virtualenv', # for scaffolding tests ] -setup(name='pyramid', - version='1.10.dev0', - description='The Pyramid Web Framework, a Pylons project', - long_description=README + '\n\n' + CHANGES, - classifiers=[ - "Development Status :: 6 - Mature", - "Intended Audience :: Developers", - "Programming Language :: Python", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Framework :: Pyramid", - "Topic :: Internet :: WWW/HTTP", - "Topic :: Internet :: WWW/HTTP :: WSGI", - "License :: Repoze Public License", - ], - keywords='web wsgi pylons pyramid', - author="Chris McDonough, Agendaless Consulting", - author_email="pylons-discuss@googlegroups.com", - url="https://trypyramid.com", - license="BSD-derived (http://www.repoze.org/LICENSE.txt)", - packages=find_packages('src', exclude=['tests']), - package_dir={'': 'src'}, - include_package_data=True, - zip_safe=False, - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', - install_requires=install_requires, - extras_require={ - ':python_version<"3.2"': ['repoze.lru >= 0.4'], - 'testing': testing_extras, - 'docs': docs_extras, - }, - tests_require=tests_require, - test_suite="tests", - entry_points="""\ +setup( + name='pyramid', + version='1.10.dev0', + description='The Pyramid Web Framework, a Pylons project', + long_description=README + '\n\n' + CHANGES, + classifiers=[ + "Development Status :: 6 - Mature", + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Framework :: Pyramid", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: WSGI", + "License :: Repoze Public License", + ], + keywords='web wsgi pylons pyramid', + author="Chris McDonough, Agendaless Consulting", + author_email="pylons-discuss@googlegroups.com", + url="https://trypyramid.com", + license="BSD-derived (http://www.repoze.org/LICENSE.txt)", + packages=find_packages('src', exclude=['tests']), + package_dir={'': 'src'}, + include_package_data=True, + zip_safe=False, + python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', + install_requires=install_requires, + extras_require={ + ':python_version<"3.2"': ['repoze.lru >= 0.4'], + 'testing': testing_extras, + 'docs': docs_extras, + }, + tests_require=tests_require, + test_suite="tests", + entry_points="""\ [pyramid.scaffold] starter=pyramid.scaffolds:StarterProjectTemplate zodb=pyramid.scaffolds:ZODBProjectTemplate @@ -113,5 +114,5 @@ setup(name='pyramid', [paste.server_runner] wsgiref = pyramid.scripts.pserve:wsgiref_server_runner cherrypy = pyramid.scripts.pserve:cherrypy_server_runner - """ - ) + """, +) diff --git a/src/pyramid/asset.py b/src/pyramid/asset.py index 9d7a3ee63..0d7575a85 100644 --- a/src/pyramid/asset.py +++ b/src/pyramid/asset.py @@ -3,14 +3,12 @@ import pkg_resources from pyramid.compat import string_types -from pyramid.path import ( - package_path, - package_name, - ) +from pyramid.path import package_path, package_name + def resolve_asset_spec(spec, pname='__main__'): if pname and not isinstance(pname, string_types): - pname = pname.__name__ # as package + pname = pname.__name__ # as package if os.path.isabs(spec): return None, spec filename = spec @@ -20,6 +18,7 @@ def resolve_asset_spec(spec, pname='__main__'): pname, filename = None, spec return pname, filename + def asset_spec_from_abspath(abspath, package): """ Try to convert an absolute path to a resource in a package to a resource specification if possible; otherwise return the @@ -28,11 +27,14 @@ def asset_spec_from_abspath(abspath, package): return abspath pp = package_path(package) + os.path.sep if abspath.startswith(pp): - relpath = abspath[len(pp):] - return '%s:%s' % (package_name(package), - relpath.replace(os.path.sep, '/')) + relpath = abspath[len(pp) :] + return '%s:%s' % ( + package_name(package), + relpath.replace(os.path.sep, '/'), + ) return abspath + # bw compat only; use pyramid.path.AssetResolver().resolve(spec).abspath() def abspath_from_asset_spec(spec, pname='__main__'): if pname is None: @@ -41,4 +43,3 @@ def abspath_from_asset_spec(spec, pname='__main__'): if pname is None: return filename return pkg_resources.resource_filename(pname, filename) - diff --git a/src/pyramid/authentication.py b/src/pyramid/authentication.py index a9604e336..f4c2b51ef 100644 --- a/src/pyramid/authentication.py +++ b/src/pyramid/authentication.py @@ -21,17 +21,11 @@ from pyramid.compat import ( bytes_, ascii_native_, native_, - ) +) -from pyramid.interfaces import ( - IAuthenticationPolicy, - IDebugLogger, - ) +from pyramid.interfaces import IAuthenticationPolicy, IDebugLogger -from pyramid.security import ( - Authenticated, - Everyone, - ) +from pyramid.security import Authenticated, Everyone from pyramid.util import strings_differ from pyramid.util import SimpleSerializer @@ -74,36 +68,41 @@ class CallbackAuthenticationPolicy(object): debug and self._log( 'call to unauthenticated_userid returned None; returning None', 'authenticated_userid', - request) + request, + ) return None if self._clean_principal(userid) is None: debug and self._log( - ('use of userid %r is disallowed by any built-in Pyramid ' - 'security policy, returning None' % userid), + ( + 'use of userid %r is disallowed by any built-in Pyramid ' + 'security policy, returning None' % userid + ), 'authenticated_userid', - request) + request, + ) return None if self.callback is None: debug and self._log( 'there was no groupfinder callback; returning %r' % (userid,), 'authenticated_userid', - request) + request, + ) return userid callback_ok = self.callback(userid, request) - if callback_ok is not None: # is not None! + if callback_ok is not None: # is not None! debug and self._log( - 'groupfinder callback returned %r; returning %r' % ( - callback_ok, userid), + 'groupfinder callback returned %r; returning %r' + % (callback_ok, userid), 'authenticated_userid', - request - ) + request, + ) return userid debug and self._log( 'groupfinder callback returned None; returning None', 'authenticated_userid', - request - ) + request, + ) def effective_principals(self, request): """ A list of effective principals derived from request. @@ -134,42 +133,45 @@ class CallbackAuthenticationPolicy(object): if userid is None: debug and self._log( - 'unauthenticated_userid returned %r; returning %r' % ( - userid, effective_principals), + 'unauthenticated_userid returned %r; returning %r' + % (userid, effective_principals), 'effective_principals', - request - ) + request, + ) return effective_principals if self._clean_principal(userid) is None: debug and self._log( - ('unauthenticated_userid returned disallowed %r; returning %r ' - 'as if it was None' % (userid, effective_principals)), + ( + 'unauthenticated_userid returned disallowed %r; returning %r ' + 'as if it was None' % (userid, effective_principals) + ), 'effective_principals', - request - ) + request, + ) return effective_principals if self.callback is None: debug and self._log( 'groupfinder callback is None, so groups is []', 'effective_principals', - request) + request, + ) groups = [] else: groups = self.callback(userid, request) debug and self._log( 'groupfinder callback returned %r as groups' % (groups,), 'effective_principals', - request) + request, + ) - if groups is None: # is None! + if groups is None: # is None! debug and self._log( - 'returning effective principals: %r' % ( - effective_principals,), + 'returning effective principals: %r' % (effective_principals,), 'effective_principals', - request - ) + request, + ) return effective_principals effective_principals.append(Authenticated) @@ -177,10 +179,9 @@ class CallbackAuthenticationPolicy(object): effective_principals.extend(groups) debug and self._log( - 'returning effective principals: %r' % ( - effective_principals,), + 'returning effective principals: %r' % (effective_principals,), 'effective_principals', - request + request, ) return effective_principals @@ -241,7 +242,8 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): self.debug and self._log( 'repoze.who identity is None, returning None', 'authenticated_userid', - request) + request, + ) return None userid = identity['repoze.who.userid'] @@ -250,21 +252,25 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): self.debug and self._log( 'repoze.who.userid is None, returning None' % userid, 'authenticated_userid', - request) + request, + ) return None if self._clean_principal(userid) is None: self.debug and self._log( - ('use of userid %r is disallowed by any built-in Pyramid ' - 'security policy, returning None' % userid), + ( + 'use of userid %r is disallowed by any built-in Pyramid ' + 'security policy, returning None' % userid + ), 'authenticated_userid', - request) + request, + ) return None if self.callback is None: return userid - if self.callback(identity, request) is not None: # is not None! + if self.callback(identity, request) is not None: # is not None! return userid def unauthenticated_userid(self, request): @@ -292,11 +298,13 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): if identity is None: self.debug and self._log( - ('repoze.who identity was None; returning %r' % - effective_principals), + ( + 'repoze.who identity was None; returning %r' + % effective_principals + ), 'effective_principals', - request - ) + request, + ) return effective_principals if self.callback is None: @@ -304,33 +312,39 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): else: groups = self.callback(identity, request) - if groups is None: # is None! + if groups is None: # is None! self.debug and self._log( - ('security policy groups callback returned None; returning %r' % - effective_principals), + ( + 'security policy groups callback returned None; returning %r' + % effective_principals + ), 'effective_principals', - request - ) + request, + ) return effective_principals userid = identity['repoze.who.userid'] if userid is None: self.debug and self._log( - ('repoze.who.userid was None; returning %r' % - effective_principals), + ( + 'repoze.who.userid was None; returning %r' + % effective_principals + ), 'effective_principals', - request - ) + request, + ) return effective_principals if self._clean_principal(userid) is None: self.debug and self._log( - ('unauthenticated_userid returned disallowed %r; returning %r ' - 'as if it was None' % (userid, effective_principals)), + ( + 'unauthenticated_userid returned disallowed %r; returning %r ' + 'as if it was None' % (userid, effective_principals) + ), 'effective_principals', - request - ) + request, + ) return effective_principals effective_principals.append(Authenticated) @@ -367,6 +381,7 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): identity = self._get_identity(request) return identifier.forget(request.environ, identity) + @implementer(IAuthenticationPolicy) class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` :term:`authentication policy` which @@ -419,6 +434,7 @@ class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): be done somewhere else or in a subclass.""" return [] + @implementer(IAuthenticationPolicy) class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): """A :app:`Pyramid` :term:`authentication policy` which @@ -586,24 +602,25 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): """ - def __init__(self, - secret, - callback=None, - cookie_name='auth_tkt', - secure=False, - include_ip=False, - timeout=None, - reissue_time=None, - max_age=None, - path="/", - http_only=False, - wild_domain=True, - debug=False, - hashalg='sha512', - parent_domain=False, - domain=None, - samesite='Lax', - ): + def __init__( + self, + secret, + callback=None, + cookie_name='auth_tkt', + secure=False, + include_ip=False, + timeout=None, + reissue_time=None, + max_age=None, + path="/", + http_only=False, + wild_domain=True, + debug=False, + hashalg='sha512', + parent_domain=False, + domain=None, + samesite='Lax', + ): self.cookie = AuthTktCookieHelper( secret, cookie_name=cookie_name, @@ -619,7 +636,7 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): parent_domain=parent_domain, domain=domain, samesite=samesite, - ) + ) self.callback = callback self.debug = debug @@ -643,12 +660,15 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): """ A list of headers which will delete appropriate cookies.""" return self.cookie.forget(request) + def b64encode(v): return base64.b64encode(bytes_(v)).strip().replace(b'\n', b'') + def b64decode(v): return base64.b64decode(bytes_(v)) + # this class licensed under the MIT license (stolen from Paste) class AuthTicket(object): """ @@ -670,9 +690,18 @@ class AuthTicket(object): """ - def __init__(self, secret, userid, ip, tokens=(), user_data='', - time=None, cookie_name='auth_tkt', secure=False, - hashalg='md5'): + def __init__( + self, + secret, + userid, + ip, + tokens=(), + user_data='', + time=None, + cookie_name='auth_tkt', + secure=False, + hashalg='md5', + ): self.secret = secret self.userid = userid self.ip = ip @@ -688,17 +717,27 @@ class AuthTicket(object): def digest(self): return calculate_digest( - self.ip, self.time, self.secret, self.userid, self.tokens, - self.user_data, self.hashalg) + self.ip, + self.time, + self.secret, + self.userid, + self.tokens, + self.user_data, + self.hashalg, + ) 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), + url_quote(self.userid), + ) if self.tokens: v += self.tokens + '!' v += self.user_data return v + # this class licensed under the MIT license (stolen from Paste) class BadTicket(Exception): """ @@ -706,10 +745,12 @@ class BadTicket(Exception): determine what the expected digest should have been, expected is set. This should not be shown by default, but can be useful for debugging. """ + def __init__(self, msg, expected=None): self.expected = expected Exception.__init__(self, msg) + # this function licensed under the MIT license (stolen from Paste) def parse_ticket(secret, ticket, ip, hashalg='md5'): """ @@ -722,37 +763,41 @@ def parse_ticket(secret, ticket, ip, hashalg='md5'): digest_size = hashlib.new(hashalg).digest_size * 2 digest = ticket[:digest_size] try: - timestamp = int(ticket[digest_size:digest_size + 8], 16) + timestamp = int(ticket[digest_size : digest_size + 8], 16) except ValueError as e: raise BadTicket('Timestamp is not a hex integer: %s' % e) try: - userid, data = ticket[digest_size + 8:].split('!', 1) + userid, data = ticket[digest_size + 8 :].split('!', 1) except ValueError: raise BadTicket('userid is not followed by !') userid = url_unquote(userid) if '!' in data: tokens, user_data = data.split('!', 1) - else: # pragma: no cover (never generated) + else: # pragma: no cover (never generated) # @@: Is this the right order? tokens = '' user_data = data - expected = calculate_digest(ip, timestamp, secret, - userid, tokens, user_data, hashalg) + expected = calculate_digest( + ip, timestamp, secret, userid, tokens, user_data, hashalg + ) # Avoid timing attacks (see # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf) if strings_differ(expected, digest): - raise BadTicket('Digest signature is not correct', - expected=(expected, digest)) + raise BadTicket( + 'Digest signature is not correct', expected=(expected, digest) + ) tokens = tokens.split(',') return (timestamp, userid, tokens, user_data) + # this function licensed under the MIT license (stolen from Paste) -def calculate_digest(ip, timestamp, secret, userid, tokens, user_data, - hashalg='md5'): +def calculate_digest( + ip, timestamp, secret, userid, tokens, user_data, hashalg='md5' +): secret = bytes_(secret, 'utf-8') userid = bytes_(userid, 'utf-8') tokens = bytes_(tokens, 'utf-8') @@ -767,24 +812,29 @@ def calculate_digest(ip, timestamp, secret, userid, tokens, user_data, # encode_ip_timestamp not required, left in for backwards compatibility ip_timestamp = encode_ip_timestamp(ip, timestamp) - hash_obj.update(ip_timestamp + secret + userid + b'\0' + - tokens + b'\0' + user_data) + hash_obj.update( + ip_timestamp + secret + userid + b'\0' + tokens + b'\0' + user_data + ) digest = hash_obj.hexdigest() hash_obj2 = hashlib.new(hashalg) hash_obj2.update(bytes_(digest) + secret) return hash_obj2.hexdigest() + # this function licensed under the MIT license (stolen from Paste) def encode_ip_timestamp(ip, timestamp): ip_chars = ''.join(map(chr, map(int, ip.split('.')))) t = int(timestamp) - ts = ((t & 0xff000000) >> 24, - (t & 0xff0000) >> 16, - (t & 0xff00) >> 8, - t & 0xff) + ts = ( + (t & 0xFF000000) >> 24, + (t & 0xFF0000) >> 16, + (t & 0xFF00) >> 8, + t & 0xFF, + ) ts_chars = ''.join(map(chr, ts)) return bytes_(ip_chars + ts_chars) + class AuthTktCookieHelper(object): """ A helper class for use in third-party authentication policy @@ -792,41 +842,43 @@ class AuthTktCookieHelper(object): :class:`pyramid.authentication.AuthTktAuthenticationPolicy` for the meanings of the constructor arguments. """ - parse_ticket = staticmethod(parse_ticket) # for tests - AuthTicket = AuthTicket # for tests - BadTicket = BadTicket # for tests - now = None # for tests + + parse_ticket = staticmethod(parse_ticket) # for tests + AuthTicket = AuthTicket # for tests + BadTicket = BadTicket # for tests + now = None # for tests userid_type_decoders = { - 'int':int, - 'unicode':lambda x: utf_8_decode(x)[0], # bw compat for old cookies + 'int': int, + 'unicode': lambda x: utf_8_decode(x)[0], # bw compat for old cookies 'b64unicode': lambda x: utf_8_decode(b64decode(x))[0], 'b64str': lambda x: b64decode(x), - } + } 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)), - } - - def __init__(self, - secret, - cookie_name='auth_tkt', - secure=False, - include_ip=False, - timeout=None, - reissue_time=None, - max_age=None, - http_only=False, - path="/", - wild_domain=True, - hashalg='md5', - parent_domain=False, - domain=None, - samesite='Lax', - ): + } + + def __init__( + self, + secret, + cookie_name='auth_tkt', + secure=False, + include_ip=False, + timeout=None, + reissue_time=None, + max_age=None, + http_only=False, + path="/", + wild_domain=True, + hashalg='md5', + parent_domain=False, + domain=None, + samesite='Lax', + ): serializer = SimpleSerializer() @@ -845,7 +897,9 @@ class AuthTktCookieHelper(object): self.secure = secure self.include_ip = include_ip self.timeout = timeout if timeout is None else int(timeout) - self.reissue_time = reissue_time if reissue_time is None else int(reissue_time) + self.reissue_time = ( + reissue_time if reissue_time is None else int(reissue_time) + ) self.max_age = max_age if max_age is None else int(max_age) self.wild_domain = wild_domain self.parent_domain = parent_domain @@ -893,16 +947,17 @@ class AuthTktCookieHelper(object): try: timestamp, userid, tokens, user_data = self.parse_ticket( - self.secret, cookie, remote_addr, self.hashalg) + self.secret, cookie, remote_addr, self.hashalg + ) except self.BadTicket: return None - now = self.now # service tests + now = self.now # service tests if now is None: now = time_mod.time() - if self.timeout and ( (timestamp + self.timeout) < now ): + if self.timeout and ((timestamp + self.timeout) < now): # the auth_tkt data has expired return None @@ -910,7 +965,7 @@ class AuthTktCookieHelper(object): user_data_info = user_data.split('|') for datum in filter(None, user_data_info): if datum.startswith(userid_typename): - userid_type = datum[len(userid_typename):] + userid_type = datum[len(userid_typename) :] decoder = self.userid_type_decoders.get(userid_type) if decoder: userid = decoder(userid) @@ -918,15 +973,18 @@ class AuthTktCookieHelper(object): reissue = self.reissue_time is not None if reissue and not hasattr(request, '_authtkt_reissued'): - if ( (now - timestamp) > self.reissue_time ): + if (now - timestamp) > self.reissue_time: # See https://github.com/Pylons/pyramid/issues#issue/108 tokens = list(filter(None, tokens)) - headers = self.remember(request, userid, max_age=self.max_age, - tokens=tokens) + headers = self.remember( + request, userid, max_age=self.max_age, tokens=tokens + ) + def reissue_authtkt(request, response): if not hasattr(request, '_authtkt_reissue_revoked'): for k, v in headers: response.headerlist.append((k, v)) + request.add_response_callback(reissue_authtkt) request._authtkt_reissued = True @@ -987,7 +1045,8 @@ class AuthTktCookieHelper(object): "AuthTktAuthenticationPolicy. Explicitly converting to string " "and storing as base64. Subsequent requests will receive a " "string as the userid, it will not be decoded back to the type " - "provided.".format(type(userid)), RuntimeWarning + "provided.".format(type(userid)), + RuntimeWarning, ) encoding, encoder = self.userid_type_encoders.get(text_type) userid = str(userid) @@ -1018,12 +1077,13 @@ class AuthTktCookieHelper(object): user_data=user_data, cookie_name=self.cookie_name, secure=self.secure, - hashalg=self.hashalg - ) + hashalg=self.hashalg, + ) cookie_value = ticket.cookie_value() return self._get_cookies(request, cookie_value, max_age) + @implementer(IAuthenticationPolicy) class SessionAuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` authentication policy which gets its data from the @@ -1123,6 +1183,7 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy): return response return HTTPForbidden() """ + def __init__(self, check, realm='Realm', debug=False): self.check = check self.realm = realm @@ -1158,7 +1219,8 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy): HTTPBasicCredentials = namedtuple( - 'HTTPBasicCredentials', ['username', 'password']) + 'HTTPBasicCredentials', ['username', 'password'] +) def extract_http_basic_credentials(request): @@ -1183,7 +1245,7 @@ def extract_http_basic_credentials(request): try: authbytes = b64decode(auth.strip()) - except (TypeError, binascii.Error): # can't decode + except (TypeError, binascii.Error): # can't decode return None # try utf-8 first, then latin-1; see discussion in @@ -1195,7 +1257,7 @@ def extract_http_basic_credentials(request): try: username, password = auth.split(':', 1) - except ValueError: # not enough values to unpack + except ValueError: # not enough values to unpack return None return HTTPBasicCredentials(username, password) diff --git a/src/pyramid/authorization.py b/src/pyramid/authorization.py index 4845762ef..974748765 100644 --- a/src/pyramid/authorization.py +++ b/src/pyramid/authorization.py @@ -6,13 +6,8 @@ from pyramid.location import lineage from pyramid.compat import is_nonstr_iter -from pyramid.security import ( - ACLAllowed, - ACLDenied, - Allow, - Deny, - Everyone, - ) +from pyramid.security import ACLAllowed, ACLDenied, Allow, Deny, Everyone + @implementer(IAuthorizationPolicy) class ACLAuthorizationPolicy(object): @@ -90,20 +85,19 @@ class ACLAuthorizationPolicy(object): ace_permissions = [ace_permissions] if permission in ace_permissions: if ace_action == Allow: - return ACLAllowed(ace, acl, permission, - principals, location) + return ACLAllowed( + ace, acl, permission, principals, location + ) else: - return ACLDenied(ace, acl, permission, - principals, location) + return ACLDenied( + ace, acl, permission, principals, location + ) # default deny (if no ACL in lineage at all, or if none of the # principals were mentioned in any ACE we found) return ACLDenied( - '<default deny>', - acl, - permission, - principals, - context) + '<default deny>', acl, permission, principals, context + ) def principals_allowed_by_permission(self, context, permission): """ Return the set of principals explicitly granted the @@ -132,14 +126,14 @@ class ACLAuthorizationPolicy(object): if ace_principal not in denied_here: allowed_here.add(ace_principal) if (ace_action == Deny) and (permission in ace_permissions): - denied_here.add(ace_principal) - if ace_principal == Everyone: - # clear the entire allowed set, as we've hit a - # deny of Everyone ala (Deny, Everyone, ALL) - allowed = set() - break - elif ace_principal in allowed: - allowed.remove(ace_principal) + denied_here.add(ace_principal) + if ace_principal == Everyone: + # clear the entire allowed set, as we've hit a + # deny of Everyone ala (Deny, Everyone, ALL) + allowed = set() + break + elif ace_principal in allowed: + allowed.remove(ace_principal) allowed.update(allowed_here) diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index a7f9c1287..4df279e94 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -7,6 +7,7 @@ WIN = platform.system() == 'Windows' try: # pragma: no cover import __pypy__ + PYPY = True except: # pragma: no cover __pypy__ = None @@ -27,20 +28,21 @@ PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 if PY2: - string_types = basestring, + 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, + 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 ``s.decode(encoding, errors)``, otherwise return ``s``""" @@ -48,6 +50,7 @@ def text_(s, encoding='latin-1', errors='strict'): return s.decode(encoding, errors) return s + def bytes_(s, encoding='latin-1', errors='strict'): """ If ``s`` is an instance of ``text_type``, return ``s.encode(encoding, errors)``, otherwise return ``s``""" @@ -55,17 +58,23 @@ def bytes_(s, encoding='latin-1', errors='strict'): return s.encode(encoding, errors) 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')`` @@ -76,13 +85,17 @@ Python 2: If ``s`` is an instance of ``text_type``, return 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)``""" @@ -90,6 +103,7 @@ else: 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)`` @@ -106,25 +120,34 @@ if PY2: 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 + 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 + 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: @@ -137,12 +160,15 @@ if PY2: # pragma: no cover locs = globs exec("""exec code in globs, locs""") - exec_("""def reraise(tp, value, tb=None): + exec_( + """def reraise(tp, value, tb=None): raise tp, value, tb -""") +""" + ) else: # pragma: no cover import builtins + exec_ = getattr(builtins, "exec") def reraise(tp, value, tb=None): @@ -156,6 +182,7 @@ else: # pragma: no cover if PY2: # pragma: no cover + def iteritems_(d): return d.iteritems() @@ -164,7 +191,10 @@ if PY2: # pragma: no cover def iterkeys_(d): return d.iterkeys() + + else: # pragma: no cover + def iteritems_(d): return d.items() @@ -178,18 +208,25 @@ else: # pragma: no cover if PY2: map_ = map else: + def map_(*arg): return list(map(*arg)) + if PY2: + def is_nonstr_iter(v): return hasattr(v, '__iter__') + + else: + 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' @@ -227,21 +264,27 @@ else: import json if PY2: + def decode_path_info(path): return path.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') + 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 + # 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): @@ -251,6 +294,7 @@ else: 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 if PY2: from inspect import getargspec @@ -262,6 +306,7 @@ if PY2: else: from itertools import zip_longest + def is_unbound_method(fn): """ This consistently verifies that the callable is bound to a diff --git a/src/pyramid/config/__init__.py b/src/pyramid/config/__init__.py index 2f4e133f0..ab5edfefe 100644 --- a/src/pyramid/config/__init__.py +++ b/src/pyramid/config/__init__.py @@ -17,17 +17,13 @@ from pyramid.interfaces import ( PHASE1_CONFIG, PHASE2_CONFIG, PHASE3_CONFIG, - ) +) from pyramid.asset import resolve_asset_spec from pyramid.authorization import ACLAuthorizationPolicy -from pyramid.compat import ( - text_, - reraise, - string_types, - ) +from pyramid.compat import text_, reraise, string_types from pyramid.events import ApplicationCreated @@ -35,21 +31,13 @@ from pyramid.exceptions import ( ConfigurationConflictError, ConfigurationError, ConfigurationExecutionError, - ) +) from pyramid.httpexceptions import default_exceptionresponse_view -from pyramid.path import ( - caller_package, - package_of, - ) +from pyramid.path import caller_package, package_of -from pyramid.registry import ( - Introspectable, - Introspector, - Registry, - undefer, - ) +from pyramid.registry import Introspectable, Introspector, Registry, undefer from pyramid.router import Router @@ -57,17 +45,9 @@ from pyramid.settings import aslist from pyramid.threadlocal import manager -from pyramid.util import ( - WeakOrderedSet, - object_description, - ) +from pyramid.util import WeakOrderedSet, object_description -from pyramid.config.util import ( - ActionInfo, - PredicateList, - action_method, - not_, -) +from pyramid.config.util import ActionInfo, PredicateList, action_method, not_ from pyramid.config.adapters import AdaptersConfiguratorMixin from pyramid.config.assets import AssetsConfiguratorMixin @@ -94,6 +74,7 @@ PHASE1_CONFIG = PHASE1_CONFIG # api PHASE2_CONFIG = PHASE2_CONFIG # api PHASE3_CONFIG = PHASE3_CONFIG # api + class Configurator( TestingConfiguratorMixin, TweensConfiguratorMixin, @@ -107,7 +88,7 @@ class Configurator( SettingsConfiguratorMixin, FactoriesConfiguratorMixin, AdaptersConfiguratorMixin, - ): +): """ A Configurator is used to configure a :app:`Pyramid` :term:`application registry`. @@ -284,8 +265,9 @@ class Configurator( ``with``-statement to make threadlocal configuration available for further configuration with an implicit commit. """ - manager = manager # for testing injection - venusian = venusian # for testing injection + + manager = manager # for testing injection + venusian = venusian # for testing injection _ainfo = None basepath = None includepath = () @@ -294,27 +276,28 @@ class Configurator( introspectable = Introspectable inspect = inspect - def __init__(self, - registry=None, - package=None, - settings=None, - root_factory=None, - authentication_policy=None, - authorization_policy=None, - renderers=None, - debug_logger=None, - locale_negotiator=None, - request_factory=None, - response_factory=None, - default_permission=None, - session_factory=None, - default_view_mapper=None, - autocommit=False, - exceptionresponse_view=default_exceptionresponse_view, - route_prefix=None, - introspection=True, - root_package=None, - ): + def __init__( + self, + registry=None, + package=None, + settings=None, + root_factory=None, + authentication_policy=None, + authorization_policy=None, + renderers=None, + debug_logger=None, + locale_negotiator=None, + request_factory=None, + response_factory=None, + default_permission=None, + session_factory=None, + default_view_mapper=None, + autocommit=False, + exceptionresponse_view=default_exceptionresponse_view, + route_prefix=None, + introspection=True, + root_package=None, + ): if package is None: package = caller_package() if root_package is None: @@ -345,23 +328,24 @@ class Configurator( session_factory=session_factory, default_view_mapper=default_view_mapper, exceptionresponse_view=exceptionresponse_view, - ) + ) - def setup_registry(self, - settings=None, - root_factory=None, - authentication_policy=None, - authorization_policy=None, - renderers=None, - debug_logger=None, - locale_negotiator=None, - request_factory=None, - response_factory=None, - default_permission=None, - session_factory=None, - default_view_mapper=None, - exceptionresponse_view=default_exceptionresponse_view, - ): + def setup_registry( + self, + settings=None, + root_factory=None, + authentication_policy=None, + authorization_policy=None, + renderers=None, + debug_logger=None, + locale_negotiator=None, + request_factory=None, + response_factory=None, + default_permission=None, + session_factory=None, + default_view_mapper=None, + exceptionresponse_view=default_exceptionresponse_view, + ): """ When you pass a non-``None`` ``registry`` argument to the :term:`Configurator` constructor, no initial setup is performed against the registry. This is because the registry you pass in may @@ -404,7 +388,9 @@ class Configurator( if exceptionresponse_view is not None: exceptionresponse_view = self.maybe_dotted(exceptionresponse_view) self.add_view(exceptionresponse_view, context=IExceptionResponse) - self.add_view(exceptionresponse_view,context=WebobWSGIHTTPException) + self.add_view( + exceptionresponse_view, context=WebobWSGIHTTPException + ) # commit below because: # @@ -424,7 +410,7 @@ class Configurator( # automatic conflict resolution. if authentication_policy and not authorization_policy: - authorization_policy = ACLAuthorizationPolicy() # default + authorization_policy = ACLAuthorizationPolicy() # default if authorization_policy: self.set_authorization_policy(authorization_policy) @@ -468,7 +454,7 @@ class Configurator( def _make_spec(self, path_or_spec): package, filename = resolve_asset_spec(path_or_spec, self.package_name) if package is None: - return filename # absolute filename + return filename # absolute filename return '%s:%s' % (package, filename) def _fix_registry(self): @@ -480,38 +466,55 @@ class Configurator( _registry = self.registry if not hasattr(_registry, 'notify'): + def notify(*events): - [ _ for _ in _registry.subscribers(events, None) ] + [_ for _ in _registry.subscribers(events, None)] + _registry.notify = notify if not hasattr(_registry, 'has_listeners'): _registry.has_listeners = True if not hasattr(_registry, 'queryAdapterOrSelf'): + def queryAdapterOrSelf(object, interface, default=None): if not interface.providedBy(object): - return _registry.queryAdapter(object, interface, - default=default) + return _registry.queryAdapter( + object, interface, default=default + ) return object + _registry.queryAdapterOrSelf = queryAdapterOrSelf if not hasattr(_registry, 'registerSelfAdapter'): - def registerSelfAdapter(required=None, provided=None, - name=empty, info=empty, event=True): - return _registry.registerAdapter(lambda x: x, - required=required, - provided=provided, name=name, - info=info, event=event) + + def registerSelfAdapter( + required=None, + provided=None, + name=empty, + info=empty, + event=True, + ): + return _registry.registerAdapter( + lambda x: x, + required=required, + provided=provided, + name=name, + info=info, + event=event, + ) + _registry.registerSelfAdapter = registerSelfAdapter if not hasattr(_registry, '_lock'): _registry._lock = threading.Lock() if not hasattr(_registry, '_clear_view_lookup_cache'): + def _clear_view_lookup_cache(): _registry._view_lookup_cache = {} - _registry._clear_view_lookup_cache = _clear_view_lookup_cache + _registry._clear_view_lookup_cache = _clear_view_lookup_cache # API @@ -530,7 +533,7 @@ class Configurator( introspector = property( _get_introspector, _set_introspector, _del_introspector - ) + ) def get_predlist(self, name): predlist = self.registry.queryUtility(IPredicateList, name=name) @@ -539,30 +542,41 @@ class Configurator( self.registry.registerUtility(predlist, IPredicateList, name=name) return predlist - - def _add_predicate(self, type, name, factory, weighs_more_than=None, - weighs_less_than=None): + def _add_predicate( + self, type, name, factory, weighs_more_than=None, weighs_less_than=None + ): factory = self.maybe_dotted(factory) discriminator = ('%s option' % type, name) intr = self.introspectable( '%s predicates' % type, discriminator, '%s predicate named %s' % (type, name), - '%s predicate' % type) + '%s predicate' % type, + ) intr['name'] = name intr['factory'] = factory intr['weighs_more_than'] = weighs_more_than intr['weighs_less_than'] = weighs_less_than + def register(): predlist = self.get_predlist(type) - predlist.add(name, factory, weighs_more_than=weighs_more_than, - weighs_less_than=weighs_less_than) - self.action(discriminator, register, introspectables=(intr,), - order=PHASE1_CONFIG) # must be registered early + predlist.add( + name, + factory, + weighs_more_than=weighs_more_than, + weighs_less_than=weighs_less_than, + ) + + self.action( + discriminator, + register, + introspectables=(intr,), + order=PHASE1_CONFIG, + ) # must be registered early @property def action_info(self): - info = self.info # usually a ZCML action (ParserInfo) if self.info + info = self.info # usually a ZCML action (ParserInfo) if self.info if not info: # Try to provide more accurate info for conflict reports if self._ainfo: @@ -571,8 +585,16 @@ class Configurator( info = ActionInfo(None, 0, '', '') return info - def action(self, discriminator, callable=None, args=(), kw=None, order=0, - introspectables=(), **extra): + def action( + self, + discriminator, + callable=None, + args=(), + kw=None, + order=0, + introspectables=(), + **extra + ): """ Register an action which will be executed when :meth:`pyramid.config.Configurator.commit` is called (or executed immediately if ``autocommit`` is ``True``). @@ -607,7 +629,7 @@ class Configurator( """ # catch nonhashable discriminators here; most unit tests use # autocommit=False, which won't catch unhashable discriminators - assert hash(discriminator) + assert hash(discriminator) if kw is None: kw = {} @@ -645,8 +667,8 @@ class Configurator( info=action_info, includepath=self.includepath, introspectables=introspectables, - ) ) + ) self.action_state.action(**action) def _get_action_state(self): @@ -663,7 +685,7 @@ class Configurator( action_state = property(_get_action_state, _set_action_state) - _ctx = action_state # bw compat + _ctx = action_state # bw compat def commit(self): """ @@ -687,7 +709,7 @@ class Configurator( self.action_state.execute_actions(introspector=self.introspector) finally: self.end() - self.action_state = ActionState() # old actions have been processed + self.action_state = ActionState() # old actions have been processed def include(self, callable, route_prefix=None): """Include a configuration callable, to support imperative @@ -800,17 +822,18 @@ class Configurator( c = getattr(module, 'includeme') except AttributeError: raise ConfigurationError( - "module %r has no attribute 'includeme'" % (module.__name__) - ) - + "module %r has no attribute 'includeme'" + % (module.__name__) + ) + spec = module.__name__ + ':' + c.__name__ sourcefile = self.inspect.getsourcefile(c) if sourcefile is None: raise ConfigurationError( 'No source file for module %r (.py file must exist, ' - 'refusing to use orphan .pyc or .pyo file).' % module.__name__) - + 'refusing to use orphan .pyc or .pyo file).' % module.__name__ + ) if action_state.processSpec(spec): with self.route_prefix_context(route_prefix): @@ -820,7 +843,7 @@ class Configurator( root_package=self.root_package, autocommit=self.autocommit, route_prefix=self.route_prefix, - ) + ) configurator.basepath = os.path.dirname(sourcefile) configurator.includepath = self.includepath + (spec,) @@ -886,7 +909,7 @@ class Configurator( autocommit=self.autocommit, route_prefix=self.route_prefix, introspection=self.introspection, - ) + ) configurator.basepath = self.basepath configurator.includepath = self.includepath configurator.info = self.info @@ -914,7 +937,7 @@ class Configurator( return relative_spec return self._make_spec(relative_spec) - absolute_resource_spec = absolute_asset_spec # b/w compat forever + absolute_resource_spec = absolute_asset_spec # b/w compat forever def begin(self, request=_marker): """ Indicate that application or test configuration has begun. @@ -940,7 +963,7 @@ class Configurator( request = current['request'] else: request = None - self.manager.push({'registry':self.registry, 'request':request}) + self.manager.push({'registry': self.registry, 'request': request}) def end(self): """ Indicate that application or test configuration has ended. @@ -961,8 +984,9 @@ class Configurator( self.commit() # this is *not* an action method (uses caller_package) - def scan(self, package=None, categories=None, onerror=None, ignore=None, - **kw): + def scan( + self, package=None, categories=None, onerror=None, ignore=None, **kw + ): """Scan a Python package and any of its subpackages for objects marked with :term:`configuration decoration` such as :class:`pyramid.view.view_config`. Any decorated object found will @@ -1021,7 +1045,7 @@ class Configurator( """ package = self.maybe_dotted(package) - if package is None: # pragma: no cover + if package is None: # pragma: no cover package = caller_package() ctorkw = {'config': self} @@ -1029,8 +1053,9 @@ class Configurator( scanner = self.venusian.Scanner(**ctorkw) - scanner.scan(package, categories=categories, onerror=onerror, - ignore=ignore) + scanner.scan( + package, categories=categories, onerror=onerror, ignore=ignore + ) def make_wsgi_app(self): """ Commits any pending configuration statements, sends a @@ -1079,8 +1104,18 @@ class ActionState(object): self._seen_files.add(spec) return True - def action(self, discriminator, callable=None, args=(), kw=None, order=0, - includepath=(), info=None, introspectables=(), **extra): + def action( + self, + discriminator, + callable=None, + args=(), + kw=None, + order=0, + includepath=(), + info=None, + introspectables=(), + **extra + ): """Add an action with the given discriminator, callable and arguments """ if kw is None: @@ -1096,8 +1131,8 @@ class ActionState(object): info=info, order=order, introspectables=introspectables, - ) ) + ) self.actions.append(action) def execute_actions(self, clear=True, introspector=None): @@ -1179,8 +1214,7 @@ class ActionState(object): if self.actions: all_actions.extend(self.actions) action_iter = resolveConflicts( - self.actions, - state=conflict_state, + self.actions, state=conflict_state ) self.actions = [] @@ -1203,9 +1237,11 @@ class ActionState(object): except Exception: t, v, tb = sys.exc_info() try: - reraise(ConfigurationExecutionError, - ConfigurationExecutionError(t, v, info), - tb) + reraise( + ConfigurationExecutionError, + ConfigurationExecutionError(t, v, info), + tb, + ) finally: del t, v, tb @@ -1290,9 +1326,12 @@ def resolveConflicts(actions, state=None): # error out if we went backward in order if state.min_order is not None and order < state.min_order: - r = ['Actions were added to order={0} after execution had moved ' - 'on to order={1}. Conflicting actions: ' - .format(order, state.min_order)] + r = [ + 'Actions were added to order={0} after execution had moved ' + 'on to order={1}. Conflicting actions: '.format( + order, state.min_order + ) + ] for i, action in actiongroup: for line in str(action['info']).rstrip().split('\n'): r.append(" " + line) @@ -1348,8 +1387,10 @@ def resolveConflicts(actions, state=None): # if the new action conflicts with the resolved action then # note the conflict, otherwise drop the action as it's # effectively overriden by the previous action - if (includepath[:len(basepath)] != basepath or - includepath == basepath): + if ( + includepath[: len(basepath)] != basepath + or includepath == basepath + ): L = conflicts.setdefault(discriminator, [baseinfo]) L.append(action['info']) @@ -1360,8 +1401,10 @@ def resolveConflicts(actions, state=None): for _, action in rest: includepath = action['includepath'] # Test whether path is a prefix of opath - if (includepath[:len(basepath)] != basepath or # not a prefix - includepath == basepath): + if ( + includepath[: len(basepath)] != basepath + or includepath == basepath # not a prefix + ): L = conflicts.setdefault(discriminator, [baseinfo]) L.append(action['info']) @@ -1389,8 +1432,14 @@ def normalize_actions(actions): def expand_action_tuple( - discriminator, callable=None, args=(), kw=None, includepath=(), - info=None, order=0, introspectables=(), + discriminator, + callable=None, + args=(), + kw=None, + includepath=(), + info=None, + order=0, + introspectables=(), ): if kw is None: kw = {} @@ -1403,7 +1452,7 @@ def expand_action_tuple( info=info, order=order, introspectables=introspectables, - ) + ) global_registries = WeakOrderedSet() diff --git a/src/pyramid/config/adapters.py b/src/pyramid/config/adapters.py index 945faa3c6..e5668c40e 100644 --- a/src/pyramid/config/adapters.py +++ b/src/pyramid/config/adapters.py @@ -4,11 +4,7 @@ from functools import update_wrapper from zope.interface import Interface -from pyramid.interfaces import ( - IResponse, - ITraverser, - IResourceURL, - ) +from pyramid.interfaces import IResponse, ITraverser, IResourceURL from pyramid.util import takes_one_arg @@ -53,33 +49,33 @@ class AdaptersConfiguratorMixin(object): predlist = self.get_predlist('subscriber') order, preds, phash = predlist.make(self, **predicates) - derived_predicates = [ self._derive_predicate(p) for p in preds ] + derived_predicates = [self._derive_predicate(p) for p in preds] derived_subscriber = self._derive_subscriber( - subscriber, - derived_predicates, - ) + subscriber, derived_predicates + ) intr.update( - {'phash':phash, - 'order':order, - 'predicates':preds, - 'derived_predicates':derived_predicates, - 'derived_subscriber':derived_subscriber, - } - ) + { + 'phash': phash, + 'order': order, + 'predicates': preds, + 'derived_predicates': derived_predicates, + 'derived_subscriber': derived_subscriber, + } + ) self.registry.registerHandler(derived_subscriber, iface) - + intr = self.introspectable( 'subscribers', id(subscriber), self.object_description(subscriber), - 'subscriber' - ) - + 'subscriber', + ) + intr['subscriber'] = subscriber intr['interfaces'] = iface - + self.action(None, register, introspectables=(intr,)) return subscriber @@ -87,8 +83,10 @@ class AdaptersConfiguratorMixin(object): derived_predicate = predicate if eventonly(predicate): + def derived_predicate(*arg): return predicate(arg[0]) + # seems pointless to try to fix __doc__, __module__, etc as # predicate will invariably be an instance @@ -98,8 +96,10 @@ class AdaptersConfiguratorMixin(object): derived_subscriber = subscriber if eventonly(subscriber): + def derived_subscriber(*arg): return subscriber(arg[0]) + if hasattr(subscriber, '__name__'): update_wrapper(derived_subscriber, subscriber) @@ -132,10 +132,11 @@ class AdaptersConfiguratorMixin(object): update_wrapper(subscriber_wrapper, subscriber) return subscriber_wrapper - + @action_method - def add_subscriber_predicate(self, name, factory, weighs_more_than=None, - weighs_less_than=None): + def add_subscriber_predicate( + self, name, factory, weighs_more_than=None, weighs_less_than=None + ): """ .. versionadded:: 1.4 @@ -159,8 +160,8 @@ class AdaptersConfiguratorMixin(object): name, factory, weighs_more_than=weighs_more_than, - weighs_less_than=weighs_less_than - ) + weighs_less_than=weighs_less_than, + ) @action_method def add_response_adapter(self, adapter, type_or_iface): @@ -178,18 +179,21 @@ class AdaptersConfiguratorMixin(object): See :ref:`using_iresponse` for more information.""" adapter = self.maybe_dotted(adapter) type_or_iface = self.maybe_dotted(type_or_iface) + def register(): reg = self.registry if adapter is None: reg.registerSelfAdapter((type_or_iface,), IResponse) else: reg.registerAdapter(adapter, (type_or_iface,), IResponse) + discriminator = (IResponse, type_or_iface) intr = self.introspectable( 'response adapters', discriminator, self.object_description(adapter), - 'response adapter') + 'response adapter', + ) intr['adapter'] = adapter intr['type'] = type_or_iface self.action(discriminator, register, introspectables=(intr,)) @@ -255,17 +259,19 @@ class AdaptersConfiguratorMixin(object): """ iface = self.maybe_dotted(iface) adapter = self.maybe_dotted(adapter) + def register(iface=iface): if iface is None: iface = Interface self.registry.registerAdapter(adapter, (iface,), ITraverser) + discriminator = ('traverser', iface) intr = self.introspectable( - 'traversers', + 'traversers', discriminator, 'traverser for %r' % iface, 'traverser', - ) + ) intr['adapter'] = adapter intr['iface'] = iface self.action(discriminator, register, introspectables=(intr,)) @@ -303,24 +309,25 @@ class AdaptersConfiguratorMixin(object): """ adapter = self.maybe_dotted(adapter) resource_iface = self.maybe_dotted(resource_iface) + def register(resource_iface=resource_iface): if resource_iface is None: resource_iface = Interface self.registry.registerAdapter( - adapter, - (resource_iface, Interface), - IResourceURL, - ) + adapter, (resource_iface, Interface), IResourceURL + ) + discriminator = ('resource url adapter', resource_iface) intr = self.introspectable( - 'resource url adapters', + 'resource url adapters', discriminator, 'resource url adapter for resource iface %r' % resource_iface, 'resource url adapter', - ) + ) intr['adapter'] = adapter intr['resource_iface'] = resource_iface self.action(discriminator, register, introspectables=(intr,)) + def eventonly(callee): return takes_one_arg(callee, argname='event') diff --git a/src/pyramid/config/assets.py b/src/pyramid/config/assets.py index b9536df42..fd8b2ee49 100644 --- a/src/pyramid/config/assets.py +++ b/src/pyramid/config/assets.py @@ -4,16 +4,14 @@ import sys from zope.interface import implementer -from pyramid.interfaces import ( - IPackageOverrides, - PHASE1_CONFIG, -) +from pyramid.interfaces import IPackageOverrides, PHASE1_CONFIG from pyramid.exceptions import ConfigurationError from pyramid.threadlocal import get_current_registry from pyramid.config.util import action_method + class OverrideProvider(pkg_resources.DefaultProvider): def __init__(self, module): pkg_resources.DefaultProvider.__init__(self, module) @@ -35,7 +33,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): if filename is not None: return filename return pkg_resources.DefaultProvider.get_resource_filename( - self, manager, resource_name) + self, manager, resource_name + ) def get_resource_stream(self, manager, resource_name): """ Return a readable file-like object for resource_name.""" @@ -45,7 +44,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): if stream is not None: return stream return pkg_resources.DefaultProvider.get_resource_stream( - self, manager, resource_name) + self, manager, resource_name + ) def get_resource_string(self, manager, resource_name): """ Return a string containing the contents of resource_name.""" @@ -55,7 +55,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): if string is not None: return string return pkg_resources.DefaultProvider.get_resource_string( - self, manager, resource_name) + self, manager, resource_name + ) def has_resource(self, resource_name): overrides = self._get_overrides() @@ -63,8 +64,7 @@ class OverrideProvider(pkg_resources.DefaultProvider): result = overrides.has_resource(resource_name) if result is not None: return result - return pkg_resources.DefaultProvider.has_resource( - self, resource_name) + return pkg_resources.DefaultProvider.has_resource(self, resource_name) def resource_isdir(self, resource_name): overrides = self._get_overrides() @@ -73,7 +73,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): if result is not None: return result return pkg_resources.DefaultProvider.resource_isdir( - self, resource_name) + self, resource_name + ) def resource_listdir(self, resource_name): overrides = self._get_overrides() @@ -82,7 +83,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): if result is not None: return result return pkg_resources.DefaultProvider.resource_listdir( - self, resource_name) + self, resource_name + ) @implementer(IPackageOverrides) @@ -193,9 +195,10 @@ class DirectoryOverride: def __call__(self, resource_name): if resource_name.startswith(self.path): - new_path = resource_name[self.pathlen:] + new_path = resource_name[self.pathlen :] return self.source, new_path + class FileOverride: def __init__(self, path, source): self.path = path @@ -215,6 +218,7 @@ class PackageAssetSource(object): the empty string, as returned by the ``FileOverride``. """ + def __init__(self, package, prefix): self.package = package if hasattr(package, '__name__'): @@ -262,6 +266,7 @@ class FSAssetSource(object): An asset source relative to a path in the filesystem. """ + def __init__(self, prefix): self.prefix = prefix @@ -305,14 +310,16 @@ class FSAssetSource(object): class AssetsConfiguratorMixin(object): - def _override(self, package, path, override_source, - PackageOverrides=PackageOverrides): + def _override( + self, package, path, override_source, PackageOverrides=PackageOverrides + ): pkg_name = package.__name__ override = self.registry.queryUtility(IPackageOverrides, name=pkg_name) if override is None: override = PackageOverrides(package) - self.registry.registerUtility(override, IPackageOverrides, - name=pkg_name) + self.registry.registerUtility( + override, IPackageOverrides, name=pkg_name + ) override.insert(path, override_source) @action_method @@ -331,7 +338,8 @@ class AssetsConfiguratorMixin(object): information about asset overrides.""" if to_override == override_with: raise ConfigurationError( - 'You cannot override an asset with itself') + 'You cannot override an asset with itself' + ) package = to_override path = '' @@ -346,7 +354,8 @@ class AssetsConfiguratorMixin(object): if not os.path.exists(override_with): raise ConfigurationError( 'Cannot override asset with an absolute path that does ' - 'not exist') + 'not exist' + ) override_isdir = os.path.isdir(override_with) override_package = None override_prefix = override_with @@ -360,22 +369,23 @@ class AssetsConfiguratorMixin(object): to_package = sys.modules[override_package] override_source = PackageAssetSource(to_package, override_prefix) - override_isdir = ( - override_prefix == '' or - override_with.endswith('/') + override_isdir = override_prefix == '' or override_with.endswith( + '/' ) if overridden_isdir and (not override_isdir): raise ConfigurationError( 'A directory cannot be overridden with a file (put a ' - 'slash at the end of override_with if necessary)') + 'slash at the end of override_with if necessary)' + ) if (not overridden_isdir) and override_isdir: raise ConfigurationError( 'A file cannot be overridden with a directory (put a ' - 'slash at the end of to_override if necessary)') + 'slash at the end of to_override if necessary)' + ) - override = _override or self._override # test jig + override = _override or self._override # test jig def register(): __import__(package) @@ -387,10 +397,11 @@ class AssetsConfiguratorMixin(object): (package, override_package, path, override_prefix), '%s -> %s' % (to_override, override_with), 'asset override', - ) + ) intr['to_override'] = to_override intr['override_with'] = override_with - self.action(None, register, introspectables=(intr,), - order=PHASE1_CONFIG) + self.action( + None, register, introspectables=(intr,), order=PHASE1_CONFIG + ) - override_resource = override_asset # bw compat + override_resource = override_asset # bw compat diff --git a/src/pyramid/config/factories.py b/src/pyramid/config/factories.py index 52248269d..2ec1558a6 100644 --- a/src/pyramid/config/factories.py +++ b/src/pyramid/config/factories.py @@ -8,18 +8,16 @@ from pyramid.interfaces import ( IRequestExtensions, IRootFactory, ISessionFactory, - ) +) from pyramid.router import default_execution_policy from pyramid.traversal import DefaultRootFactory -from pyramid.util import ( - get_callable_name, - InstancePropertyHelper, - ) +from pyramid.util import get_callable_name, InstancePropertyHelper from pyramid.config.util import action_method + class FactoriesConfiguratorMixin(object): @action_method def set_root_factory(self, factory): @@ -41,10 +39,12 @@ class FactoriesConfiguratorMixin(object): self.registry.registerUtility(factory, IRootFactory) self.registry.registerUtility(factory, IDefaultRootFactory) # b/c - intr = self.introspectable('root factories', - None, - self.object_description(factory), - 'root factory') + intr = self.introspectable( + 'root factories', + None, + self.object_description(factory), + 'root factory', + ) intr['factory'] = factory self.action(IRootFactory, register, introspectables=(intr,)) @@ -67,9 +67,13 @@ class FactoriesConfiguratorMixin(object): def register(): self.registry.registerUtility(factory, ISessionFactory) - intr = self.introspectable('session factory', None, - self.object_description(factory), - 'session factory') + + intr = self.introspectable( + 'session factory', + None, + self.object_description(factory), + 'session factory', + ) intr['factory'] = factory self.action(ISessionFactory, register, introspectables=(intr,)) @@ -97,9 +101,13 @@ class FactoriesConfiguratorMixin(object): def register(): self.registry.registerUtility(factory, IRequestFactory) - intr = self.introspectable('request factory', None, - self.object_description(factory), - 'request factory') + + intr = self.introspectable( + 'request factory', + None, + self.object_description(factory), + 'request factory', + ) intr['factory'] = factory self.action(IRequestFactory, register, introspectables=(intr,)) @@ -122,18 +130,19 @@ class FactoriesConfiguratorMixin(object): def register(): self.registry.registerUtility(factory, IResponseFactory) - intr = self.introspectable('response factory', None, - self.object_description(factory), - 'response factory') + intr = self.introspectable( + 'response factory', + None, + self.object_description(factory), + 'response factory', + ) intr['factory'] = factory self.action(IResponseFactory, register, introspectables=(intr,)) @action_method - def add_request_method(self, - callable=None, - name=None, - property=False, - reify=False): + def add_request_method( + self, callable=None, name=None, property=False, reify=False + ): """ Add a property or method to the request object. When adding a method to the request, ``callable`` may be any @@ -177,7 +186,8 @@ class FactoriesConfiguratorMixin(object): property = property or reify if property: name, callable = InstancePropertyHelper.make_property( - callable, name=name, reify=reify) + callable, name=name, reify=reify + ) elif name is None: name = callable.__name__ else: @@ -196,23 +206,31 @@ class FactoriesConfiguratorMixin(object): if callable is None: self.action(('request extensions', name), None) elif property: - intr = self.introspectable('request extensions', name, - self.object_description(callable), - 'request property') + intr = self.introspectable( + 'request extensions', + name, + self.object_description(callable), + 'request property', + ) intr['callable'] = callable intr['property'] = True intr['reify'] = reify - self.action(('request extensions', name), register, - introspectables=(intr,)) + self.action( + ('request extensions', name), register, introspectables=(intr,) + ) else: - intr = self.introspectable('request extensions', name, - self.object_description(callable), - 'request method') + intr = self.introspectable( + 'request extensions', + name, + self.object_description(callable), + 'request method', + ) intr['callable'] = callable intr['property'] = False intr['reify'] = False - self.action(('request extensions', name), register, - introspectables=(intr,)) + self.action( + ('request extensions', name), register, introspectables=(intr,) + ) @action_method def set_execution_policy(self, policy): @@ -231,9 +249,12 @@ class FactoriesConfiguratorMixin(object): def register(): self.registry.registerUtility(policy, IExecutionPolicy) - intr = self.introspectable('execution policy', None, - self.object_description(policy), - 'execution policy') + intr = self.introspectable( + 'execution policy', + None, + self.object_description(policy), + 'execution policy', + ) intr['policy'] = policy self.action(IExecutionPolicy, register, introspectables=(intr,)) diff --git a/src/pyramid/config/i18n.py b/src/pyramid/config/i18n.py index 5dabe2845..6e7334448 100644 --- a/src/pyramid/config/i18n.py +++ b/src/pyramid/config/i18n.py @@ -1,13 +1,11 @@ -from pyramid.interfaces import ( - ILocaleNegotiator, - ITranslationDirectories, - ) +from pyramid.interfaces import ILocaleNegotiator, ITranslationDirectories from pyramid.exceptions import ConfigurationError from pyramid.path import AssetResolver from pyramid.config.util import action_method + class I18NConfiguratorMixin(object): @action_method def set_locale_negotiator(self, negotiator): @@ -30,11 +28,16 @@ class I18NConfiguratorMixin(object): :class:`pyramid.config.Configurator` constructor can be used to achieve the same purpose. """ + def register(): self._set_locale_negotiator(negotiator) - intr = self.introspectable('locale negotiator', None, - self.object_description(negotiator), - 'locale negotiator') + + intr = self.introspectable( + 'locale negotiator', + None, + self.object_description(negotiator), + 'locale negotiator', + ) intr['negotiator'] = negotiator self.action(ILocaleNegotiator, register, introspectables=(intr,)) @@ -97,10 +100,15 @@ class I18NConfiguratorMixin(object): asset = resolver.resolve(spec) directory = asset.abspath() if not asset.isdir(): - raise ConfigurationError('"%s" is not a directory' % - directory) - intr = self.introspectable('translation directories', directory, - spec, 'translation directory') + raise ConfigurationError( + '"%s" is not a directory' % directory + ) + intr = self.introspectable( + 'translation directories', + directory, + spec, + 'translation directory', + ) intr['directory'] = directory intr['spec'] = spec introspectables.append(intr) @@ -117,4 +125,3 @@ class I18NConfiguratorMixin(object): tdirs.insert(0, directory) self.action(None, register, introspectables=introspectables) - diff --git a/src/pyramid/config/predicates.py b/src/pyramid/config/predicates.py index bda763161..cdbf68ca4 100644 --- a/src/pyramid/config/predicates.py +++ b/src/pyramid/config/predicates.py @@ -1,2 +1,3 @@ import zope.deprecation + zope.deprecation.moved('pyramid.predicates', 'Pyramid 1.10') diff --git a/src/pyramid/config/rendering.py b/src/pyramid/config/rendering.py index 0d55c41e8..948199636 100644 --- a/src/pyramid/config/rendering.py +++ b/src/pyramid/config/rendering.py @@ -1,7 +1,4 @@ -from pyramid.interfaces import ( - IRendererFactory, - PHASE1_CONFIG, - ) +from pyramid.interfaces import IRendererFactory, PHASE1_CONFIG from pyramid import renderers from pyramid.config.util import action_method @@ -9,13 +6,14 @@ from pyramid.config.util import action_method DEFAULT_RENDERERS = ( ('json', renderers.json_renderer_factory), ('string', renderers.string_renderer_factory), - ) +) + class RenderingConfiguratorMixin(object): def add_default_renderers(self): for name, renderer in DEFAULT_RENDERERS: self.add_renderer(name, renderer) - + @action_method def add_renderer(self, name, factory): """ @@ -36,16 +34,23 @@ class RenderingConfiguratorMixin(object): # as a name if not name: name = '' + def register(): self.registry.registerUtility(factory, IRendererFactory, name=name) - intr = self.introspectable('renderer factories', - name, - self.object_description(factory), - 'renderer factory') + + intr = self.introspectable( + 'renderer factories', + name, + self.object_description(factory), + 'renderer factory', + ) intr['factory'] = factory intr['name'] = name # we need to register renderers early (in phase 1) because they are # used during view configuration (which happens in phase 3) - self.action((IRendererFactory, name), register, order=PHASE1_CONFIG, - introspectables=(intr,)) - + self.action( + (IRendererFactory, name), + register, + order=PHASE1_CONFIG, + introspectables=(intr,), + ) diff --git a/src/pyramid/config/routes.py b/src/pyramid/config/routes.py index 5d05429a7..46b8921cd 100644 --- a/src/pyramid/config/routes.py +++ b/src/pyramid/config/routes.py @@ -7,16 +7,13 @@ from pyramid.interfaces import ( IRouteRequest, IRoutesMapper, PHASE2_CONFIG, - ) +) from pyramid.exceptions import ConfigurationError from pyramid.request import route_request_iface from pyramid.urldispatch import RoutesMapper -from pyramid.util import ( - as_sorted_tuple, - is_nonstr_iter, -) +from pyramid.util import as_sorted_tuple, is_nonstr_iter import pyramid.predicates @@ -26,26 +23,29 @@ from pyramid.config.util import ( predvalseq, ) + class RoutesConfiguratorMixin(object): @action_method - def add_route(self, - name, - pattern=None, - factory=None, - for_=None, - header=None, - xhr=None, - accept=None, - path_info=None, - request_method=None, - request_param=None, - traverse=None, - custom_predicates=(), - use_global_views=False, - path=None, - pregenerator=None, - static=False, - **predicates): + def add_route( + self, + name, + pattern=None, + factory=None, + for_=None, + header=None, + xhr=None, + accept=None, + path_info=None, + request_method=None, + request_param=None, + traverse=None, + custom_predicates=(), + use_global_views=False, + path=None, + pregenerator=None, + static=False, + **predicates + ): """ Add a :term:`route configuration` to the current configuration state, as well as possibly a :term:`view configuration` to be used to specify a :term:`view callable` @@ -297,27 +297,31 @@ class RoutesConfiguratorMixin(object): """ if custom_predicates: warnings.warn( - ('The "custom_predicates" argument to Configurator.add_route ' - 'is deprecated as of Pyramid 1.5. Use ' - '"config.add_route_predicate" and use the registered ' - 'route predicate as a predicate argument to add_route ' - 'instead. See "Adding A Third Party View, Route, or ' - 'Subscriber Predicate" in the "Hooks" chapter of the ' - 'documentation for more information.'), + ( + 'The "custom_predicates" argument to Configurator.add_route ' + 'is deprecated as of Pyramid 1.5. Use ' + '"config.add_route_predicate" and use the registered ' + 'route predicate as a predicate argument to add_route ' + 'instead. See "Adding A Third Party View, Route, or ' + 'Subscriber Predicate" in the "Hooks" chapter of the ' + 'documentation for more information.' + ), DeprecationWarning, - stacklevel=3 - ) + stacklevel=3, + ) if accept is not None: if not is_nonstr_iter(accept): if '*' in accept: warnings.warn( - ('Passing a media range to the "accept" argument of ' - 'Configurator.add_route is deprecated as of Pyramid ' - '1.10. Use a list of explicit media types.'), + ( + 'Passing a media range to the "accept" argument of ' + 'Configurator.add_route is deprecated as of Pyramid ' + '1.10. Use a list of explicit media types.' + ), DeprecationWarning, stacklevel=3, - ) + ) # XXX switch this to False when range support is dropped accept = [normalize_accept_offer(accept, allow_range=True)] @@ -347,15 +351,16 @@ class RoutesConfiguratorMixin(object): pattern = parsed.path original_pregenerator = pregenerator + def external_url_pregenerator(request, elements, kw): if '_app_url' in kw: raise ValueError( 'You cannot generate a path to an external route ' 'pattern via request.route_path nor pass an _app_url ' 'to request.route_url when generating a URL for an ' - 'external route pattern (pattern was "%s") ' % - (pattern,) - ) + 'external route pattern (pattern was "%s") ' + % (pattern,) + ) if '_scheme' in kw: scheme = kw['_scheme'] elif parsed.scheme: @@ -365,8 +370,7 @@ class RoutesConfiguratorMixin(object): kw['_app_url'] = '{0}://{1}'.format(scheme, parsed.netloc) if original_pregenerator: - elements, kw = original_pregenerator( - request, elements, kw) + elements, kw = original_pregenerator(request, elements, kw) return elements, kw pregenerator = external_url_pregenerator @@ -379,10 +383,9 @@ class RoutesConfiguratorMixin(object): introspectables = [] - intr = self.introspectable('routes', - name, - '%s (pattern: %r)' % (name, pattern), - 'route') + intr = self.introspectable( + 'routes', name, '%s (pattern: %r)' % (name, pattern), 'route' + ) intr['name'] = name intr['pattern'] = pattern intr['factory'] = factory @@ -404,17 +407,21 @@ class RoutesConfiguratorMixin(object): introspectables.append(intr) if factory: - factory_intr = self.introspectable('root factories', - name, - self.object_description(factory), - 'root factory') + factory_intr = self.introspectable( + 'root factories', + name, + self.object_description(factory), + 'root factory', + ) factory_intr['factory'] = factory factory_intr['route_name'] = name factory_intr.relate('routes', name) introspectables.append(factory_intr) def register_route_request_iface(): - request_iface = self.registry.queryUtility(IRouteRequest, name=name) + request_iface = self.registry.queryUtility( + IRouteRequest, name=name + ) if request_iface is None: if use_global_views: bases = (IRequest,) @@ -422,7 +429,8 @@ class RoutesConfiguratorMixin(object): bases = () request_iface = route_request_iface(name, bases) self.registry.registerUtility( - request_iface, IRouteRequest, name=name) + request_iface, IRouteRequest, name=name + ) def register_connect(): pvals = predicates.copy() @@ -436,15 +444,19 @@ class RoutesConfiguratorMixin(object): accept=accept, traverse=traverse, custom=predvalseq(custom_predicates), - ) ) + ) predlist = self.get_predlist('route') _, preds, _ = predlist.make(self, **pvals) route = mapper.connect( - name, pattern, factory, predicates=preds, - pregenerator=pregenerator, static=static - ) + name, + pattern, + factory, + predicates=preds, + pregenerator=pregenerator, + static=static, + ) intr['object'] = route return route @@ -455,12 +467,17 @@ class RoutesConfiguratorMixin(object): # But IRouteRequest interfaces must be registered before we begin to # process view registrations (in phase 3) - self.action(('route', name), register_route_request_iface, - order=PHASE2_CONFIG, introspectables=introspectables) + self.action( + ('route', name), + register_route_request_iface, + order=PHASE2_CONFIG, + introspectables=introspectables, + ) @action_method - def add_route_predicate(self, name, factory, weighs_more_than=None, - weighs_less_than=None): + def add_route_predicate( + self, name, factory, weighs_more_than=None, weighs_less_than=None + ): """ Adds a route predicate factory. The view predicate can later be named as a keyword argument to :meth:`pyramid.config.Configurator.add_route`. @@ -481,8 +498,8 @@ class RoutesConfiguratorMixin(object): name, factory, weighs_more_than=weighs_more_than, - weighs_less_than=weighs_less_than - ) + weighs_less_than=weighs_less_than, + ) def add_default_route_predicates(self): p = pyramid.predicates @@ -496,7 +513,7 @@ class RoutesConfiguratorMixin(object): ('effective_principals', p.EffectivePrincipalsPredicate), ('custom', p.CustomPredicate), ('traverse', p.TraversePredicate), - ): + ): self.add_route_predicate(name, factory) def get_routes_mapper(self): @@ -541,8 +558,7 @@ class RoutesConfiguratorMixin(object): old_route_prefix = '' route_prefix = '{}/{}'.format( - old_route_prefix.rstrip('/'), - route_prefix.lstrip('/'), + old_route_prefix.rstrip('/'), route_prefix.lstrip('/') ) route_prefix = route_prefix.strip('/') diff --git a/src/pyramid/config/security.py b/src/pyramid/config/security.py index c7afbcf4e..3b55c41d7 100644 --- a/src/pyramid/config/security.py +++ b/src/pyramid/config/security.py @@ -8,7 +8,7 @@ from pyramid.interfaces import ( IDefaultPermission, PHASE1_CONFIG, PHASE2_CONFIG, - ) +) from pyramid.csrf import LegacySessionCSRFStoragePolicy from pyramid.exceptions import ConfigurationError @@ -16,8 +16,8 @@ from pyramid.util import as_sorted_tuple from pyramid.config.util import action_method -class SecurityConfiguratorMixin(object): +class SecurityConfiguratorMixin(object): def add_default_security(self): self.set_csrf_storage_policy(LegacySessionCSRFStoragePolicy()) @@ -35,20 +35,30 @@ class SecurityConfiguratorMixin(object): achieve the same purpose. """ + def register(): self._set_authentication_policy(policy) if self.registry.queryUtility(IAuthorizationPolicy) is None: raise ConfigurationError( 'Cannot configure an authentication policy without ' 'also configuring an authorization policy ' - '(use the set_authorization_policy method)') - intr = self.introspectable('authentication policy', None, - self.object_description(policy), - 'authentication policy') + '(use the set_authorization_policy method)' + ) + + intr = self.introspectable( + 'authentication policy', + None, + self.object_description(policy), + 'authentication policy', + ) intr['policy'] = policy # authentication policy used by view config (phase 3) - self.action(IAuthenticationPolicy, register, order=PHASE2_CONFIG, - introspectables=(intr,)) + self.action( + IAuthenticationPolicy, + register, + order=PHASE2_CONFIG, + introspectables=(intr,), + ) def _set_authentication_policy(self, policy): policy = self.maybe_dotted(policy) @@ -67,8 +77,10 @@ class SecurityConfiguratorMixin(object): :class:`pyramid.config.Configurator` constructor can be used to achieve the same purpose. """ + def register(): self._set_authorization_policy(policy) + def ensure(): if self.autocommit: return @@ -76,16 +88,24 @@ class SecurityConfiguratorMixin(object): raise ConfigurationError( 'Cannot configure an authorization policy without ' 'also configuring an authentication policy ' - '(use the set_authorization_policy method)') + '(use the set_authorization_policy method)' + ) - intr = self.introspectable('authorization policy', None, - self.object_description(policy), - 'authorization policy') + intr = self.introspectable( + 'authorization policy', + None, + self.object_description(policy), + 'authorization policy', + ) intr['policy'] = policy # authorization policy used by view config (phase 3) and # authentication policy (phase 2) - self.action(IAuthorizationPolicy, register, order=PHASE1_CONFIG, - introspectables=(intr,)) + self.action( + IAuthorizationPolicy, + register, + order=PHASE1_CONFIG, + introspectables=(intr,), + ) self.action(None, ensure) def _set_authorization_policy(self, policy): @@ -133,21 +153,25 @@ class SecurityConfiguratorMixin(object): :class:`pyramid.config.Configurator` constructor can be used to achieve the same purpose. """ + def register(): self.registry.registerUtility(permission, IDefaultPermission) - intr = self.introspectable('default permission', - None, - permission, - 'default permission') + + intr = self.introspectable( + 'default permission', None, permission, 'default permission' + ) intr['value'] = permission - perm_intr = self.introspectable('permissions', - permission, - permission, - 'permission') + perm_intr = self.introspectable( + 'permissions', permission, permission, 'permission' + ) perm_intr['value'] = permission # default permission used during view registration (phase 3) - self.action(IDefaultPermission, register, order=PHASE1_CONFIG, - introspectables=(intr, perm_intr,)) + self.action( + IDefaultPermission, + register, + order=PHASE1_CONFIG, + introspectables=(intr, perm_intr), + ) def add_permission(self, permission_name): """ @@ -161,11 +185,8 @@ class SecurityConfiguratorMixin(object): config.add_permission('view') """ intr = self.introspectable( - 'permissions', - permission_name, - permission_name, - 'permission' - ) + 'permissions', permission_name, permission_name, 'permission' + ) intr['value'] = permission_name self.action(None, introspectables=(intr,)) @@ -217,22 +238,30 @@ class SecurityConfiguratorMixin(object): """ options = DefaultCSRFOptions( - require_csrf, token, header, safe_methods, callback, + require_csrf, token, header, safe_methods, callback ) + def register(): self.registry.registerUtility(options, IDefaultCSRFOptions) - intr = self.introspectable('default csrf view options', - None, - options, - 'default csrf view options') + + intr = self.introspectable( + 'default csrf view options', + None, + options, + 'default csrf view options', + ) intr['require_csrf'] = require_csrf intr['token'] = token intr['header'] = header intr['safe_methods'] = as_sorted_tuple(safe_methods) intr['callback'] = callback - self.action(IDefaultCSRFOptions, register, order=PHASE1_CONFIG, - introspectables=(intr,)) + self.action( + IDefaultCSRFOptions, + register, + order=PHASE1_CONFIG, + introspectables=(intr,), + ) @action_method def set_csrf_storage_policy(self, policy): @@ -245,12 +274,13 @@ class SecurityConfiguratorMixin(object): how to generate and persist CSRF tokens. """ + def register(): self.registry.registerUtility(policy, ICSRFStoragePolicy) - intr = self.introspectable('csrf storage policy', - None, - policy, - 'csrf storage policy') + + intr = self.introspectable( + 'csrf storage policy', None, policy, 'csrf storage policy' + ) intr['policy'] = policy self.action(ICSRFStoragePolicy, register, introspectables=(intr,)) diff --git a/src/pyramid/config/settings.py b/src/pyramid/config/settings.py index 11a1f7d8c..07b469c29 100644 --- a/src/pyramid/config/settings.py +++ b/src/pyramid/config/settings.py @@ -2,6 +2,7 @@ import os from pyramid.settings import asbool, aslist + class SettingsConfiguratorMixin(object): def _set_settings(self, mapping): if mapping is None: @@ -60,11 +61,13 @@ def Settings(d=None, _environ_=os.environ, **kw): d.update(**kw) eget = _environ_.get + def expand_key(key): keys = [key] if not key.startswith('pyramid.'): keys.append('pyramid.' + key) return keys + def S(settings_key, env_key=None, type_=str, default=False): value = default keys = expand_key(settings_key) @@ -74,6 +77,7 @@ def Settings(d=None, _environ_=os.environ, **kw): value = eget(env_key, value) value = type_(value) d.update({k: value for k in keys}) + def O(settings_key, override_key): # noqa: E743 for key in expand_key(settings_key): d[key] = d[key] or d[override_key] diff --git a/src/pyramid/config/testing.py b/src/pyramid/config/testing.py index 1daf5cdeb..1655df52c 100644 --- a/src/pyramid/config/testing.py +++ b/src/pyramid/config/testing.py @@ -5,22 +5,25 @@ from pyramid.interfaces import ( IAuthorizationPolicy, IAuthenticationPolicy, IRendererFactory, - ) +) from pyramid.renderers import RendererHelper -from pyramid.traversal import ( - decode_path_info, - split_path_info, - ) +from pyramid.traversal import decode_path_info, split_path_info from pyramid.config.util import action_method + class TestingConfiguratorMixin(object): # testing API - def testing_securitypolicy(self, userid=None, groupids=(), - permissive=True, remember_result=None, - forget_result=None): + def testing_securitypolicy( + self, + userid=None, + groupids=(), + permissive=True, + remember_result=None, + forget_result=None, + ): """Unit/integration testing helper: Registers a pair of faux :app:`Pyramid` security policies: a :term:`authentication policy` and a :term:`authorization policy`. @@ -64,9 +67,10 @@ class TestingConfiguratorMixin(object): The ``forget_result`` argument. """ from pyramid.testing import DummySecurityPolicy + policy = DummySecurityPolicy( userid, groupids, permissive, remember_result, forget_result - ) + ) self.registry.registerUtility(policy, IAuthorizationPolicy) self.registry.registerUtility(policy, IAuthenticationPolicy) return policy @@ -85,6 +89,7 @@ class TestingConfiguratorMixin(object): :func:`pyramid.traversal.find_resource` is called with an equivalent path string or tuple. """ + class DummyTraverserFactory: def __init__(self, context): self.context = context @@ -93,14 +98,22 @@ class TestingConfiguratorMixin(object): path = decode_path_info(request.environ['PATH_INFO']) ob = resources[path] traversed = split_path_info(path) - return {'context':ob, 'view_name':'','subpath':(), - 'traversed':traversed, 'virtual_root':ob, - 'virtual_root_path':(), 'root':ob} - self.registry.registerAdapter(DummyTraverserFactory, (Interface,), - ITraverser) + return { + 'context': ob, + 'view_name': '', + 'subpath': (), + 'traversed': traversed, + 'virtual_root': ob, + 'virtual_root_path': (), + 'root': ob, + } + + self.registry.registerAdapter( + DummyTraverserFactory, (Interface,), ITraverser + ) return resources - testing_models = testing_resources # b/w compat + testing_models = testing_resources # b/w compat @action_method def testing_add_subscriber(self, event_iface=None): @@ -122,8 +135,10 @@ class TestingConfiguratorMixin(object): """ event_iface = self.maybe_dotted(event_iface) L = [] + def subscriber(*event): L.extend(event) + self.add_subscriber(subscriber, event_iface) return L @@ -149,19 +164,22 @@ class TestingConfiguratorMixin(object): """ from pyramid.testing import DummyRendererFactory + helper = RendererHelper(name=path, registry=self.registry) - factory = self.registry.queryUtility(IRendererFactory, name=helper.type) + factory = self.registry.queryUtility( + IRendererFactory, name=helper.type + ) if not isinstance(factory, DummyRendererFactory): factory = DummyRendererFactory(helper.type, factory) - self.registry.registerUtility(factory, IRendererFactory, - name=helper.type) + self.registry.registerUtility( + factory, IRendererFactory, name=helper.type + ) from pyramid.testing import DummyTemplateRenderer + if renderer is None: renderer = DummyTemplateRenderer() factory.add(path, renderer) return renderer testing_add_template = testing_add_renderer - - diff --git a/src/pyramid/config/tweens.py b/src/pyramid/config/tweens.py index 8bf21cf71..a90008784 100644 --- a/src/pyramid/config/tweens.py +++ b/src/pyramid/config/tweens.py @@ -2,26 +2,17 @@ from zope.interface import implementer from pyramid.interfaces import ITweens -from pyramid.compat import ( - string_types, - is_nonstr_iter, - ) +from pyramid.compat import string_types, is_nonstr_iter from pyramid.exceptions import ConfigurationError -from pyramid.tweens import ( - MAIN, - INGRESS, - EXCVIEW, - ) +from pyramid.tweens import MAIN, INGRESS, EXCVIEW -from pyramid.util import ( - is_string_or_iterable, - TopologicalSorter, - ) +from pyramid.util import is_string_or_iterable, TopologicalSorter from pyramid.config.util import action_method + class TweensConfiguratorMixin(object): def add_tween(self, tween_factory, under=None, over=None): """ @@ -104,8 +95,9 @@ class TweensConfiguratorMixin(object): For more information, see :ref:`registering_tweens`. """ - return self._add_tween(tween_factory, under=under, over=over, - explicit=False) + return self._add_tween( + tween_factory, under=under, over=over, explicit=False + ) def add_default_tweens(self): self.add_tween(EXCVIEW) @@ -116,8 +108,9 @@ class TweensConfiguratorMixin(object): if not isinstance(tween_factory, string_types): raise ConfigurationError( 'The "tween_factory" argument to add_tween must be a ' - 'dotted name to a globally importable object, not %r' % - tween_factory) + 'dotted name to a globally importable object, not %r' + % tween_factory + ) name = tween_factory @@ -130,7 +123,8 @@ class TweensConfiguratorMixin(object): if p is not None: if not is_string_or_iterable(p): raise ConfigurationError( - '"%s" must be a string or iterable, not %s' % (t, p)) + '"%s" must be a string or iterable, not %s' % (t, p) + ) if over is INGRESS or is_nonstr_iter(over) and INGRESS in over: raise ConfigurationError('%s cannot be over INGRESS' % name) @@ -150,15 +144,16 @@ class TweensConfiguratorMixin(object): if explicit: tweens.add_explicit(name, tween_factory) else: - tweens.add_implicit(name, tween_factory, under=under, over=over) + tweens.add_implicit( + name, tween_factory, under=under, over=over + ) discriminator = ('tween', name, explicit) tween_type = explicit and 'explicit' or 'implicit' - intr = self.introspectable('tweens', - discriminator, - name, - '%s tween' % tween_type) + intr = self.introspectable( + 'tweens', discriminator, name, '%s tween' % tween_type + ) intr['name'] = name intr['factory'] = tween_factory intr['type'] = tween_type @@ -167,6 +162,7 @@ class TweensConfiguratorMixin(object): introspectables.append(intr) self.action(discriminator, register, introspectables=introspectables) + @implementer(ITweens) class Tweens(object): def __init__(self): @@ -174,7 +170,8 @@ class Tweens(object): default_before=None, default_after=INGRESS, first=INGRESS, - last=MAIN) + last=MAIN, + ) self.explicit = [] def add_explicit(self, name, factory): diff --git a/src/pyramid/config/util.py b/src/pyramid/config/util.py index 05d810f6f..627b78b6f 100644 --- a/src/pyramid/config/util.py +++ b/src/pyramid/config/util.py @@ -4,23 +4,18 @@ import traceback from webob.acceptparse import Accept from zope.interface import implementer -from pyramid.compat import ( - bytes_, - is_nonstr_iter -) +from pyramid.compat import bytes_, is_nonstr_iter from pyramid.interfaces import IActionInfo from pyramid.exceptions import ConfigurationError from pyramid.predicates import Notted from pyramid.registry import predvalseq -from pyramid.util import ( - TopologicalSorter, - takes_one_arg, -) +from pyramid.util import TopologicalSorter, takes_one_arg TopologicalSorter = TopologicalSorter # support bw-compat imports takes_one_arg = takes_one_arg # support bw-compat imports + @implementer(IActionInfo) class ActionInfo(object): def __init__(self, file, line, function, src): @@ -34,10 +29,12 @@ class ActionInfo(object): src = '\n'.join(' %s' % x for x in srclines) return 'Line %s of file %s:\n%s' % (self.line, self.file, src) + def action_method(wrapped): """ Wrapper to provide the right conflict info report data when a method that calls Configurator.action calls another that does the same. Not a documented API but used by some external systems.""" + def wrapper(self, *arg, **kw): if self._ainfo is None: self._ainfo = [] @@ -55,10 +52,10 @@ def action_method(wrapped): # extra stack frame. This should no longer be necessary in # Python 3.5.1 last_frame = ActionInfo(*f[-1]) - if last_frame.function == 'extract_stack': # pragma: no cover + if last_frame.function == 'extract_stack': # pragma: no cover f.pop() info = ActionInfo(*f[-backframes]) - except Exception: # pragma: no cover + except Exception: # pragma: no cover info = ActionInfo(None, 0, '', '') self._ainfo.append(info) try: @@ -112,6 +109,7 @@ class not_(object): .. versionadded:: 1.5 """ + def __init__(self, value): self.value = value @@ -119,8 +117,8 @@ class not_(object): # under = after # over = before -class PredicateList(object): +class PredicateList(object): def __init__(self): self.sorter = TopologicalSorter() self.last_added = None @@ -133,11 +131,8 @@ class PredicateList(object): ## weighs_less_than = LAST self.last_added = name self.sorter.add( - name, - factory, - after=weighs_more_than, - before=weighs_less_than, - ) + name, factory, after=weighs_more_than, before=weighs_less_than + ) def names(self): # Return the list of valid predicate names. @@ -161,7 +156,7 @@ class PredicateList(object): preds = [] for n, (name, predicate_factory) in enumerate(ordered): vals = kw.pop(name, None) - if vals is None: # XXX should this be a sentinel other than None? + if vals is None: # XXX should this be a sentinel other than None? continue if not isinstance(vals, predvalseq): vals = (vals,) @@ -183,8 +178,9 @@ class PredicateList(object): preds.append(pred) if kw: from difflib import get_close_matches + closest = [] - names = [ name for name, _ in ordered ] + names = [name for name, _ in ordered] for name in kw: closest.extend(get_close_matches(name, names, 3)) @@ -266,8 +262,7 @@ def sort_accept_offers(offers, order=None): parsed = Accept.parse_offer(value) type_w = find_order_index( - parsed.type + '/' + parsed.subtype, - max_weight, + parsed.type + '/' + parsed.subtype, max_weight ) if parsed.params: diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index e6baa7c17..277b207fd 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -6,11 +6,7 @@ import os import warnings from webob.acceptparse import Accept -from zope.interface import ( - Interface, - implementedBy, - implementer, - ) +from zope.interface import Interface, implementedBy, implementer from zope.interface.interfaces import IInterface from pyramid.interfaces import ( @@ -31,7 +27,7 @@ from pyramid.interfaces import ( IViewDeriverInfo, IViewMapperFactory, PHASE1_CONFIG, - ) +) from pyramid import renderers @@ -42,20 +38,17 @@ from pyramid.compat import ( url_quote, WIN, is_nonstr_iter, - ) +) from pyramid.decorator import reify -from pyramid.exceptions import ( - ConfigurationError, - PredicateMismatch, - ) +from pyramid.exceptions import ConfigurationError, PredicateMismatch from pyramid.httpexceptions import ( HTTPForbidden, HTTPNotFound, default_exceptionresponse_view, - ) +) from pyramid.registry import Deferred @@ -66,10 +59,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, TopologicalSorter import pyramid.predicates import pyramid.viewderivers @@ -91,19 +81,19 @@ from pyramid.config.util import ( normalize_accept_offer, predvalseq, 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 -view_description = view_description # bw-compat +DefaultViewMapper = DefaultViewMapper # bw-compat +preserve_view_attrs = preserve_view_attrs # bw-compat +requestonly = requestonly # bw-compat +view_description = view_description # bw-compat + @implementer(IMultiView) class MultiView(object): - def __init__(self, name): self.name = name self.media_views = {} @@ -181,21 +171,22 @@ class MultiView(object): continue raise PredicateMismatch(self.name) + def attr_wrapped_view(view, info): - accept, order, phash = (info.options.get('accept', None), - getattr(info, 'order', MAX_ORDER), - getattr(info, 'phash', DEFAULT_PHASH)) + accept, order, phash = ( + info.options.get('accept', None), + getattr(info, 'order', MAX_ORDER), + getattr(info, 'phash', DEFAULT_PHASH), + ) # this is a little silly but we don't want to decorate the original # function with attributes that indicate accept, order, and phash, # so we use a wrapper - if ( - (accept is None) and - (order == MAX_ORDER) and - (phash == DEFAULT_PHASH) - ): - return view # defaults + if (accept is None) and (order == MAX_ORDER) and (phash == DEFAULT_PHASH): + return view # defaults + def attr_view(context, request): return view(context, request) + attr_view.__accept__ = accept attr_view.__order__ = order attr_view.__phash__ = phash @@ -203,31 +194,38 @@ def attr_wrapped_view(view, info): attr_view.__permission__ = info.options.get('permission') return attr_view + attr_wrapped_view.options = ('accept', 'attr', 'permission') + def predicated_view(view, info): preds = info.predicates if not preds: return view + def predicate_wrapper(context, request): for predicate in preds: if not predicate(context, request): view_name = getattr(view, '__name__', view) raise PredicateMismatch( - 'predicate mismatch for view %s (%s)' % ( - view_name, predicate.text())) + 'predicate mismatch for view %s (%s)' + % (view_name, predicate.text()) + ) return view(context, request) + def checker(context, request): - return all((predicate(context, request) for predicate in - preds)) + return all((predicate(context, request) for predicate in preds)) + predicate_wrapper.__predicated__ = checker predicate_wrapper.__predicates__ = preds return predicate_wrapper + def viewdefaults(wrapped): """ Decorator for add_view-like methods which takes into account __view_defaults__ attached to view it is passed. Not a documented API but used by some external systems.""" + def wrapper(self, *arg, **kw): defaults = {} if arg: @@ -238,19 +236,23 @@ def viewdefaults(wrapped): if inspect.isclass(view): defaults = getattr(view, '__view_defaults__', {}).copy() if '_backframes' not in kw: - kw['_backframes'] = 1 # for action_method + kw['_backframes'] = 1 # for action_method defaults.update(kw) return wrapped(self, *arg, **defaults) + return functools.wraps(wrapped)(wrapper) + def combine_decorators(*decorators): def decorated(view_callable): # reversed() allows a more natural ordering in the api for decorator in reversed(decorators): view_callable = decorator(view_callable) return view_callable + return decorated + class ViewsConfiguratorMixin(object): @viewdefaults @action_method @@ -281,7 +283,8 @@ class ViewsConfiguratorMixin(object): check_csrf=None, require_csrf=None, exception_only=False, - **view_options): + **view_options + ): """ Add a :term:`view configuration` to the current configuration state. Arguments to ``add_view`` are broken down below into *predicate* arguments and *non-predicate* @@ -804,42 +807,48 @@ class ViewsConfiguratorMixin(object): """ if custom_predicates: warnings.warn( - ('The "custom_predicates" argument to Configurator.add_view ' - 'is deprecated as of Pyramid 1.5. Use ' - '"config.add_view_predicate" and use the registered ' - 'view predicate as a predicate argument to add_view instead. ' - 'See "Adding A Third Party View, Route, or Subscriber ' - 'Predicate" in the "Hooks" chapter of the documentation ' - 'for more information.'), + ( + 'The "custom_predicates" argument to Configurator.add_view ' + 'is deprecated as of Pyramid 1.5. Use ' + '"config.add_view_predicate" and use the registered ' + 'view predicate as a predicate argument to add_view instead. ' + 'See "Adding A Third Party View, Route, or Subscriber ' + 'Predicate" in the "Hooks" chapter of the documentation ' + 'for more information.' + ), DeprecationWarning, stacklevel=4, - ) + ) if check_csrf is not None: warnings.warn( - ('The "check_csrf" argument to Configurator.add_view is ' - 'deprecated as of Pyramid 1.7. Use the "require_csrf" option ' - 'instead or see "Checking CSRF Tokens Automatically" in the ' - '"Sessions" chapter of the documentation for more ' - 'information.'), + ( + 'The "check_csrf" argument to Configurator.add_view is ' + 'deprecated as of Pyramid 1.7. Use the "require_csrf" option ' + 'instead or see "Checking CSRF Tokens Automatically" in the ' + '"Sessions" chapter of the documentation for more ' + 'information.' + ), DeprecationWarning, stacklevel=4, - ) + ) if accept is not None: if is_nonstr_iter(accept): raise ConfigurationError( - 'A list is not supported in the "accept" view predicate.', + 'A list is not supported in the "accept" view predicate.' ) if '*' in accept: warnings.warn( - ('Passing a media range to the "accept" argument of ' - 'Configurator.add_view is deprecated as of Pyramid 1.10. ' - 'Use explicit media types to avoid ambiguities in ' - 'content negotiation that may impact your users.'), + ( + 'Passing a media range to the "accept" argument of ' + 'Configurator.add_view is deprecated as of Pyramid 1.10. ' + 'Use explicit media types to avoid ambiguities in ' + 'content negotiation that may impact your users.' + ), DeprecationWarning, stacklevel=4, - ) + ) # XXX when media ranges are gone, switch allow_range=False accept = normalize_accept_offer(accept, allow_range=True) @@ -856,17 +865,21 @@ class ViewsConfiguratorMixin(object): if not view: if renderer: + def view(context, request): return {} + else: - raise ConfigurationError('"view" was not specified and ' - 'no "renderer" specified') + raise ConfigurationError( + '"view" was not specified and ' 'no "renderer" specified' + ) if request_type is not None: request_type = self.maybe_dotted(request_type) if not IInterface.providedBy(request_type): raise ConfigurationError( - 'request_type must be an interface, not %s' % request_type) + 'request_type must be an interface, not %s' % request_type + ) if context is None: context = for_ @@ -875,7 +888,8 @@ class ViewsConfiguratorMixin(object): if exception_only and not isexc: raise ConfigurationError( 'view "context" must be an exception type when ' - '"exception_only" is True') + '"exception_only" is True' + ) r_context = context if r_context is None: @@ -885,24 +899,26 @@ class ViewsConfiguratorMixin(object): if isinstance(renderer, string_types): renderer = renderers.RendererHelper( - name=renderer, package=self.package, - registry=self.registry) + name=renderer, package=self.package, registry=self.registry + ) introspectables = [] ovals = view_options.copy() - ovals.update(dict( - xhr=xhr, - request_method=request_method, - path_info=path_info, - request_param=request_param, - header=header, - accept=accept, - containment=containment, - request_type=request_type, - match_param=match_param, - check_csrf=check_csrf, - custom=predvalseq(custom_predicates), - )) + ovals.update( + dict( + xhr=xhr, + request_method=request_method, + path_info=path_info, + request_param=request_param, + header=header, + accept=accept, + containment=containment, + request_type=request_type, + match_param=match_param, + check_csrf=check_csrf, + custom=predvalseq(custom_predicates), + ) + ) def discrim_func(): # We need to defer the discriminator until we know what the phash @@ -924,80 +940,82 @@ class ViewsConfiguratorMixin(object): order, preds, phash = predlist.make(self, **pvals) - view_intr.update({ - 'phash': phash, - 'order': order, - 'predicates': preds, - }) + view_intr.update( + {'phash': phash, 'order': order, 'predicates': preds} + ) return ('view', context, name, route_name, phash) discriminator = Deferred(discrim_func) if inspect.isclass(view) and attr: view_desc = 'method %r of %s' % ( - attr, self.object_description(view)) + attr, + self.object_description(view), + ) else: view_desc = self.object_description(view) tmpl_intr = None - view_intr = self.introspectable('views', - discriminator, - view_desc, - 'view') - view_intr.update(dict( - name=name, - context=context, - exception_only=exception_only, - containment=containment, - request_param=request_param, - request_methods=request_method, - route_name=route_name, - attr=attr, - xhr=xhr, - accept=accept, - header=header, - path_info=path_info, - match_param=match_param, - check_csrf=check_csrf, - http_cache=http_cache, - require_csrf=require_csrf, - callable=view, - mapper=mapper, - decorator=decorator, - )) + view_intr = self.introspectable( + 'views', discriminator, view_desc, 'view' + ) + view_intr.update( + dict( + name=name, + context=context, + exception_only=exception_only, + containment=containment, + request_param=request_param, + request_methods=request_method, + route_name=route_name, + attr=attr, + xhr=xhr, + accept=accept, + header=header, + path_info=path_info, + match_param=match_param, + check_csrf=check_csrf, + http_cache=http_cache, + require_csrf=require_csrf, + callable=view, + mapper=mapper, + decorator=decorator, + ) + ) view_intr.update(view_options) introspectables.append(view_intr) def register(permission=permission, renderer=renderer): request_iface = IRequest if route_name is not None: - request_iface = self.registry.queryUtility(IRouteRequest, - name=route_name) + request_iface = self.registry.queryUtility( + IRouteRequest, name=route_name + ) if request_iface is None: # route configuration should have already happened in # phase 2 raise ConfigurationError( - 'No route named %s found for view registration' % - route_name) + 'No route named %s found for view registration' + % route_name + ) if renderer is None: # use default renderer if one exists (reg'd in phase 1) if self.registry.queryUtility(IRendererFactory) is not None: renderer = renderers.RendererHelper( - name=None, - package=self.package, - registry=self.registry - ) + name=None, package=self.package, registry=self.registry + ) renderer_type = getattr(renderer, 'type', None) intrspc = self.introspector if ( - renderer_type is not None and - tmpl_intr is not None and - intrspc is not None and - intrspc.get('renderer factories', renderer_type) is not None - ): + renderer_type is not None + and tmpl_intr is not None + and intrspc is not None + and intrspc.get('renderer factories', renderer_type) + is not None + ): # allow failure of registered template factories to be deferred # until view execution, like other bad renderer factories; if # we tried to relate this to an existing renderer factory @@ -1013,8 +1031,9 @@ class ViewsConfiguratorMixin(object): register_view(IViewClassifier, request_iface, derived_view) if isexc: derived_exc_view = derive_view(True, renderer) - register_view(IExceptionViewClassifier, request_iface, - derived_exc_view) + register_view( + IExceptionViewClassifier, request_iface, derived_exc_view + ) if exception_only: derived_view = derived_exc_view @@ -1085,8 +1104,8 @@ class ViewsConfiguratorMixin(object): for view_type in (IView, ISecuredView, IMultiView): old_view = registered( - (classifier, request_iface, r_context), - view_type, name) + (classifier, request_iface, r_context), view_type, name + ) if old_view is not None: break @@ -1109,8 +1128,8 @@ class ViewsConfiguratorMixin(object): derived_view, (classifier, request_iface, context), view_iface, - name - ) + name, + ) else: # - A view or multiview was already registered for this @@ -1136,32 +1155,33 @@ class ViewsConfiguratorMixin(object): # unregister any existing views self.registry.adapters.unregister( (classifier, request_iface, r_context), - view_type, name=name) + view_type, + name=name, + ) self.registry.registerAdapter( multiview, (classifier, request_iface, context), - IMultiView, name=name) + IMultiView, + name=name, + ) if mapper: mapper_intr = self.introspectable( 'view mappers', discriminator, 'view mapper for %s' % view_desc, - 'view mapper' - ) + 'view mapper', + ) mapper_intr['mapper'] = mapper mapper_intr.relate('views', discriminator) introspectables.append(mapper_intr) if route_name: - view_intr.relate('routes', route_name) # see add_route + view_intr.relate('routes', route_name) # see add_route if renderer is not None and renderer.name and '.' in renderer.name: # the renderer is a template tmpl_intr = self.introspectable( - 'templates', - discriminator, - renderer.name, - 'template' - ) + 'templates', discriminator, renderer.name, 'template' + ) tmpl_intr.relate('views', discriminator) tmpl_intr['name'] = renderer.name tmpl_intr['type'] = renderer.type @@ -1170,11 +1190,8 @@ class ViewsConfiguratorMixin(object): if permission is not None: # if a permission exists, register a permission introspectable perm_intr = self.introspectable( - 'permissions', - permission, - permission, - 'permission' - ) + 'permissions', permission, permission, 'permission' + ) perm_intr['value'] = permission perm_intr.relate('views', discriminator) introspectables.append(perm_intr) @@ -1192,8 +1209,10 @@ class ViewsConfiguratorMixin(object): def _apply_view_derivers(self, info): # These derivers are not really derivers and so have fixed order - outer_derivers = [('attr_wrapped_view', attr_wrapped_view), - ('predicated_view', predicated_view)] + outer_derivers = [ + ('attr_wrapped_view', attr_wrapped_view), + ('predicated_view', predicated_view), + ] view = info.original_view derivers = self.registry.getUtility(IViewDerivers) @@ -1202,8 +1221,9 @@ class ViewsConfiguratorMixin(object): return view @action_method - def add_view_predicate(self, name, factory, weighs_more_than=None, - weighs_less_than=None): + def add_view_predicate( + self, name, factory, weighs_more_than=None, weighs_less_than=None + ): """ .. versionadded:: 1.4 @@ -1226,8 +1246,8 @@ class ViewsConfiguratorMixin(object): name, factory, weighs_more_than=weighs_more_than, - weighs_less_than=weighs_less_than - ) + weighs_less_than=weighs_less_than, + ) def add_default_view_predicates(self): p = pyramid.predicates @@ -1245,7 +1265,7 @@ class ViewsConfiguratorMixin(object): ('physical_path', p.PhysicalPathPredicate), ('effective_principals', p.EffectivePrincipalsPredicate), ('custom', p.CustomPredicate), - ): + ): self.add_view_predicate(name, factory) def add_default_accept_view_order(self): @@ -1261,10 +1281,7 @@ class ViewsConfiguratorMixin(object): @action_method def add_accept_view_order( - self, - value, - weighs_more_than=None, - weighs_less_than=None, + self, value, weighs_more_than=None, weighs_less_than=None ): """ Specify an ordering preference for the ``accept`` view option used @@ -1293,19 +1310,22 @@ class ViewsConfiguratorMixin(object): .. versionadded:: 1.10 """ + def check_type(than): than_type, than_subtype, than_params = Accept.parse_offer(than) # text/plain vs text/html;charset=utf8 if bool(offer_params) ^ bool(than_params): raise ConfigurationError( 'cannot compare a media type with params to one without ' - 'params') + 'params' + ) # text/plain;charset=utf8 vs text/html;charset=utf8 if offer_params and ( offer_subtype != than_subtype or offer_type != than_type ): raise ConfigurationError( - 'cannot compare params across different media types') + 'cannot compare params across different media types' + ) def normalize_types(thans): thans = [normalize_accept_offer(than) for than in thans] @@ -1328,25 +1348,27 @@ class ViewsConfiguratorMixin(object): discriminator = ('accept view order', value) intr = self.introspectable( - 'accept view order', - value, - value, - 'accept view order') + 'accept view order', value, value, 'accept view order' + ) intr['value'] = value intr['weighs_more_than'] = weighs_more_than intr['weighs_less_than'] = weighs_less_than + def register(): sorter = self.registry.queryUtility(IAcceptOrder) if sorter is None: sorter = TopologicalSorter() self.registry.registerUtility(sorter, IAcceptOrder) sorter.add( - value, value, - before=weighs_more_than, - after=weighs_less_than, + value, value, before=weighs_more_than, after=weighs_less_than ) - self.action(discriminator, register, introspectables=(intr,), - order=PHASE1_CONFIG) # must be registered before add_view + + self.action( + discriminator, + register, + introspectables=(intr,), + order=PHASE1_CONFIG, + ) # must be registered before add_view @action_method def add_view_deriver(self, deriver, name=None, under=None, over=None): @@ -1390,8 +1412,9 @@ class ViewsConfiguratorMixin(object): name = deriver.__name__ if name in (INGRESS, VIEW): - raise ConfigurationError('%s is a reserved view deriver name' - % name) + raise ConfigurationError( + '%s is a reserved view deriver name' % name + ) if under is None: under = 'decorated_view' @@ -1415,15 +1438,12 @@ class ViewsConfiguratorMixin(object): raise ConfigurationError('%s cannot be under "mapped_view"' % name) discriminator = ('view deriver', name) - intr = self.introspectable( - 'view derivers', - name, - name, - 'view deriver') + intr = self.introspectable('view derivers', name, name, 'view deriver') intr['name'] = name intr['deriver'] = deriver intr['under'] = under intr['over'] = over + def register(): derivers = self.registry.queryUtility(IViewDerivers) if derivers is None: @@ -1435,8 +1455,13 @@ class ViewsConfiguratorMixin(object): ) self.registry.registerUtility(derivers, IViewDerivers) derivers.add(name, deriver, before=over, after=under) - self.action(discriminator, register, introspectables=(intr,), - order=PHASE1_CONFIG) # must be registered before add_view + + self.action( + discriminator, + register, + introspectables=(intr,), + order=PHASE1_CONFIG, + ) # must be registered before add_view def add_default_view_derivers(self): d = pyramid.viewderivers @@ -1450,12 +1475,7 @@ class ViewsConfiguratorMixin(object): ] last = INGRESS for name, deriver in derivers: - self.add_view_deriver( - deriver, - name=name, - under=last, - over=VIEW, - ) + self.add_view_deriver(deriver, name=name, under=last, over=VIEW) last = name # leave the csrf_view loosely coupled to the rest of the pipeline @@ -1547,26 +1567,39 @@ class ViewsConfiguratorMixin(object): return self._derive_view(view, attr=attr, renderer=renderer) # b/w compat - def _derive_view(self, view, permission=None, predicates=(), - attr=None, renderer=None, wrapper_viewname=None, - viewname=None, accept=None, order=MAX_ORDER, - phash=DEFAULT_PHASH, decorator=None, route_name=None, - mapper=None, http_cache=None, context=None, - require_csrf=None, exception_only=False, - extra_options=None): + def _derive_view( + self, + view, + permission=None, + predicates=(), + attr=None, + renderer=None, + wrapper_viewname=None, + viewname=None, + accept=None, + order=MAX_ORDER, + phash=DEFAULT_PHASH, + decorator=None, + route_name=None, + mapper=None, + http_cache=None, + context=None, + require_csrf=None, + exception_only=False, + extra_options=None, + ): view = self.maybe_dotted(view) mapper = self.maybe_dotted(mapper) if isinstance(renderer, string_types): renderer = renderers.RendererHelper( - name=renderer, package=self.package, - registry=self.registry) + name=renderer, package=self.package, registry=self.registry + ) if renderer is None: # use default renderer if one exists if self.registry.queryUtility(IRendererFactory) is not None: renderer = renderers.RendererHelper( - name=None, - package=self.package, - registry=self.registry) + name=None, package=self.package, registry=self.registry + ) options = dict( view=view, @@ -1581,7 +1614,7 @@ class ViewsConfiguratorMixin(object): decorator=decorator, http_cache=http_cache, require_csrf=require_csrf, - route_name=route_name + route_name=route_name, ) if extra_options: options.update(extra_options) @@ -1624,7 +1657,7 @@ class ViewsConfiguratorMixin(object): mapper=None, match_param=None, **view_options - ): + ): """ Add a forbidden view to the current configuration state. The view will be called when Pyramid or application code raises a :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of @@ -1658,13 +1691,18 @@ class ViewsConfiguratorMixin(object): The view is created using ``exception_only=True``. """ for arg in ( - 'name', 'permission', 'context', 'for_', 'require_csrf', + 'name', + 'permission', + 'context', + 'for_', + 'require_csrf', 'exception_only', ): if arg in view_options: raise ConfigurationError( '%s may not be used as an argument to add_forbidden_view' - % (arg,)) + % (arg,) + ) if view is None: view = default_exceptionresponse_view @@ -1691,11 +1729,11 @@ class ViewsConfiguratorMixin(object): require_csrf=False, attr=attr, renderer=renderer, - ) + ) settings.update(view_options) return self.add_view(**settings) - set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias + set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias @viewdefaults @action_method @@ -1720,7 +1758,7 @@ class ViewsConfiguratorMixin(object): match_param=None, append_slash=False, **view_options - ): + ): """ Add a default :term:`Not Found View` to the current configuration state. The view will be called when Pyramid or application code raises an :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g., when a @@ -1794,13 +1832,18 @@ class ViewsConfiguratorMixin(object): """ for arg in ( - 'name', 'permission', 'context', 'for_', 'require_csrf', + 'name', + 'permission', + 'context', + 'for_', + 'require_csrf', 'exception_only', ): if arg in view_options: raise ConfigurationError( '%s may not be used as an argument to add_notfound_view' - % (arg,)) + % (arg,) + ) if view is None: view = default_exceptionresponse_view @@ -1825,13 +1868,13 @@ class ViewsConfiguratorMixin(object): route_name=route_name, permission=NO_PERMISSION_REQUIRED, require_csrf=False, - ) + ) settings.update(view_options) if append_slash: view = self._derive_view(view, attr=attr, renderer=renderer) if IResponse.implementedBy(append_slash): view = AppendSlashNotFoundViewFactory( - view, redirect_class=append_slash, + view, redirect_class=append_slash ) else: view = AppendSlashNotFoundViewFactory(view) @@ -1841,7 +1884,7 @@ class ViewsConfiguratorMixin(object): settings['renderer'] = renderer return self.add_view(**settings) - set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias + set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias @viewdefaults @action_method @@ -1851,7 +1894,7 @@ class ViewsConfiguratorMixin(object): context=None, # force all other arguments to be specified as key=value **view_options - ): + ): """ Add an :term:`exception view` for the specified ``exception`` to the current configuration state. The view will be called when Pyramid or application code raises the given exception. @@ -1867,21 +1910,28 @@ class ViewsConfiguratorMixin(object): .. versionadded:: 1.8 """ for arg in ( - 'name', 'for_', 'exception_only', 'require_csrf', 'permission', + 'name', + 'for_', + 'exception_only', + 'require_csrf', + 'permission', ): if arg in view_options: raise ConfigurationError( '%s may not be used as an argument to add_exception_view' - % (arg,)) + % (arg,) + ) if context is None: context = Exception - view_options.update(dict( - view=view, - context=context, - exception_only=True, - permission=NO_PERMISSION_REQUIRED, - require_csrf=False, - )) + view_options.update( + dict( + view=view, + context=context, + exception_only=True, + permission=NO_PERMISSION_REQUIRED, + require_csrf=False, + ) + ) return self.add_view(**view_options) @action_method @@ -1909,17 +1959,25 @@ class ViewsConfiguratorMixin(object): can be used to achieve the same purpose. """ mapper = self.maybe_dotted(mapper) + def register(): self.registry.registerUtility(mapper, IViewMapperFactory) + # IViewMapperFactory is looked up as the result of view config # in phase 3 - intr = self.introspectable('view mappers', - IViewMapperFactory, - self.object_description(mapper), - 'default view mapper') + intr = self.introspectable( + 'view mappers', + IViewMapperFactory, + self.object_description(mapper), + 'default view mapper', + ) intr['mapper'] = mapper - self.action(IViewMapperFactory, register, order=PHASE1_CONFIG, - introspectables=(intr,)) + self.action( + IViewMapperFactory, + register, + order=PHASE1_CONFIG, + introspectables=(intr,), + ) @action_method def add_static_view(self, name, path, **kw): @@ -2054,14 +2112,15 @@ class ViewsConfiguratorMixin(object): self.registry.registerUtility(info, IStaticURLInfo) return info + def isexception(o): if IInterface.providedBy(o): if IException.isEqualOrExtendedBy(o): return True - return ( - isinstance(o, Exception) or - (inspect.isclass(o) and (issubclass(o, Exception))) - ) + return isinstance(o, Exception) or ( + inspect.isclass(o) and (issubclass(o, Exception)) + ) + def runtime_exc_view(view, excview): # create a view callable which can pretend to be both a normal view @@ -2094,6 +2153,7 @@ def runtime_exc_view(view, excview): fn = getattr(selected_view, attr, None) if fn is not None: return fn(context, request) + return wrapper # these methods are dynamic per-request and should dispatch to their @@ -2104,16 +2164,12 @@ def runtime_exc_view(view, excview): wrapper_view.__predicates__ = wrap_fn('__predicates__') return wrapper_view + @implementer(IViewDeriverInfo) class ViewDeriverInfo(object): - def __init__(self, - view, - registry, - package, - predicates, - exception_only, - options, - ): + def __init__( + self, view, registry, package, predicates, exception_only, options + ): self.original_view = view self.registry = registry self.package = package @@ -2125,6 +2181,7 @@ class ViewDeriverInfo(object): def settings(self): return self.registry.settings + @implementer(IStaticURLInfo) class StaticURLInfo(object): def __init__(self): @@ -2134,12 +2191,13 @@ class StaticURLInfo(object): def generate(self, path, request, **kw): for (url, spec, route_name) in self.registrations: if path.startswith(spec): - subpath = path[len(spec):] - if WIN: # pragma: no cover - subpath = subpath.replace('\\', '/') # windows + subpath = path[len(spec) :] + if WIN: # pragma: no cover + subpath = subpath.replace('\\', '/') # windows if self.cache_busters: subpath, kw = self._bust_asset_path( - request, spec, subpath, kw) + request, spec, subpath, kw + ) if url is None: kw['subpath'] = subpath return request.route_url(route_name, **kw) @@ -2147,8 +2205,11 @@ class StaticURLInfo(object): app_url, qs, anchor = parse_url_overrides(request, kw) parsed = url_parse(url) if not parsed.scheme: - url = urlparse.urlunparse(parsed._replace( - scheme=request.environ['wsgi.url_scheme'])) + url = urlparse.urlunparse( + parsed._replace( + scheme=request.environ['wsgi.url_scheme'] + ) + ) subpath = url_quote(subpath) result = urljoin(url, subpath) return result + qs + anchor @@ -2161,7 +2222,7 @@ class StaticURLInfo(object): # appending a slash here if the spec doesn't have one is # required for proper prefix matching done in ``generate`` # (``subpath = path[len(spec):]``). - if os.path.isabs(spec): # FBO windows + if os.path.isabs(spec): # FBO windows sep = os.sep else: sep = '/' @@ -2189,8 +2250,9 @@ class StaticURLInfo(object): cache_max_age = extra.pop('cache_max_age', None) # create a view - view = static_view(spec, cache_max_age=cache_max_age, - use_subpath=True) + view = static_view( + spec, cache_max_age=cache_max_age, use_subpath=True + ) # Mutate extra to allow factory, etc to be passed through here. # Treat permission specially because we'd like to default to @@ -2207,7 +2269,7 @@ class StaticURLInfo(object): # register a route using the computed view, permission, and # pattern, plus any extras passed to us via add_static_view - pattern = "%s*subpath" % name # name already ends with slash + pattern = "%s*subpath" % name # name already ends with slash if config.route_prefix: route_name = '__%s/%s' % (config.route_prefix, name) else: @@ -2233,10 +2295,9 @@ class StaticURLInfo(object): # url, spec, route_name registrations.append((url, spec, route_name)) - intr = config.introspectable('static views', - name, - 'static view for %r' % name, - 'static view') + intr = config.introspectable( + 'static views', name, 'static view for %r' % name, 'static view' + ) intr['name'] = name intr['spec'] = spec @@ -2245,7 +2306,7 @@ class StaticURLInfo(object): def add_cache_buster(self, config, spec, cachebust, explicit=False): # ensure the spec always has a trailing slash as we only support # adding cache busters to folders, not files - if os.path.isabs(spec): # FBO windows + if os.path.isabs(spec): # FBO windows sep = os.sep else: sep = '/' @@ -2282,10 +2343,9 @@ class StaticURLInfo(object): cache_busters.insert(new_idx, (spec, cachebust, explicit)) - intr = config.introspectable('cache busters', - spec, - 'cache buster for %r' % spec, - 'cache buster') + intr = config.introspectable( + 'cache busters', spec, 'cache buster for %r' % spec, 'cache buster' + ) intr['cachebust'] = cachebust intr['path'] = spec intr['explicit'] = explicit @@ -2318,9 +2378,8 @@ class StaticURLInfo(object): kw['pathspec'] = pathspec kw['rawspec'] = rawspec for spec_, cachebust, explicit in reversed(self.cache_busters): - if ( - (explicit and rawspec.startswith(spec_)) or - (not explicit and pathspec.startswith(spec_)) + if (explicit and rawspec.startswith(spec_)) or ( + not explicit and pathspec.startswith(spec_) ): subpath, kw = cachebust(request, subpath, kw) break diff --git a/src/pyramid/config/zca.py b/src/pyramid/config/zca.py index bcd5c31e3..7bf637632 100644 --- a/src/pyramid/config/zca.py +++ b/src/pyramid/config/zca.py @@ -1,5 +1,6 @@ from pyramid.threadlocal import get_current_registry + class ZCAConfiguratorMixin(object): def hook_zca(self): """ Call :func:`zope.component.getSiteManager.sethook` with the @@ -10,11 +11,12 @@ class ZCAConfiguratorMixin(object): :app:`Pyramid` :term:`application registry` rather than the Zope 'global' registry.""" from zope.component import getSiteManager + getSiteManager.sethook(get_current_registry) def unhook_zca(self): """ Call :func:`zope.component.getSiteManager.reset` to undo the action of :meth:`pyramid.config.Configurator.hook_zca`.""" from zope.component import getSiteManager - getSiteManager.reset() + getSiteManager.reset() diff --git a/src/pyramid/csrf.py b/src/pyramid/csrf.py index da171d9af..582d6a641 100644 --- a/src/pyramid/csrf.py +++ b/src/pyramid/csrf.py @@ -4,22 +4,11 @@ from webob.cookies import CookieProfile from zope.interface import implementer -from pyramid.compat import ( - bytes_, - urlparse, - text_, -) -from pyramid.exceptions import ( - BadCSRFOrigin, - BadCSRFToken, -) +from pyramid.compat import bytes_, urlparse, 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 @implementer(ICSRFStoragePolicy) @@ -37,6 +26,7 @@ class LegacySessionCSRFStoragePolicy(object): .. versionadded:: 1.9 """ + def new_csrf_token(self, request): """ Sets a new CSRF token into the session and returns it. """ return request.session.new_csrf_token() @@ -50,7 +40,8 @@ class LegacySessionCSRFStoragePolicy(object): """ Returns ``True`` if the ``supplied_token`` is valid.""" expected_token = self.get_csrf_token(request) return not strings_differ( - bytes_(expected_token), bytes_(supplied_token)) + bytes_(expected_token), bytes_(supplied_token) + ) @implementer(ICSRFStoragePolicy) @@ -68,6 +59,7 @@ class SessionCSRFStoragePolicy(object): .. versionadded:: 1.9 """ + _token_factory = staticmethod(lambda: text_(uuid.uuid4().hex)) def __init__(self, key='_csrft_'): @@ -91,7 +83,8 @@ class SessionCSRFStoragePolicy(object): """ Returns ``True`` if the ``supplied_token`` is valid.""" expected_token = self.get_csrf_token(request) return not strings_differ( - bytes_(expected_token), bytes_(supplied_token)) + bytes_(expected_token), bytes_(supplied_token) + ) @implementer(ICSRFStoragePolicy) @@ -111,10 +104,19 @@ class CookieCSRFStoragePolicy(object): Added the ``samesite`` option and made the default ``'Lax'``. """ + _token_factory = staticmethod(lambda: text_(uuid.uuid4().hex)) - def __init__(self, cookie_name='csrf_token', secure=False, httponly=False, - domain=None, max_age=None, path='/', samesite='Lax'): + def __init__( + self, + cookie_name='csrf_token', + secure=False, + httponly=False, + domain=None, + max_age=None, + path='/', + samesite='Lax', + ): serializer = SimpleSerializer() self.cookie_profile = CookieProfile( cookie_name=cookie_name, @@ -132,11 +134,10 @@ class CookieCSRFStoragePolicy(object): """ Sets a new CSRF token into the request and returns it. """ token = self._token_factory() request.cookies[self.cookie_name] = token + def set_cookie(request, response): - self.cookie_profile.set_cookies( - response, - token, - ) + self.cookie_profile.set_cookies(response, token) + request.add_response_callback(set_cookie) return token @@ -153,7 +154,8 @@ class CookieCSRFStoragePolicy(object): """ Returns ``True`` if the ``supplied_token`` is valid.""" expected_token = self.get_csrf_token(request) return not strings_differ( - bytes_(expected_token), bytes_(supplied_token)) + bytes_(expected_token), bytes_(supplied_token) + ) def get_csrf_token(request): @@ -182,10 +184,9 @@ def new_csrf_token(request): return csrf.new_csrf_token(request) -def check_csrf_token(request, - token='csrf_token', - header='X-CSRF-Token', - raises=True): +def check_csrf_token( + request, token='csrf_token', header='X-CSRF-Token', raises=True +): """ Check the CSRF token returned by the :class:`pyramid.interfaces.ICSRFStoragePolicy` implementation against the value in ``request.POST.get(token)`` (if a POST request) or @@ -267,6 +268,7 @@ def check_csrf_origin(request, trusted_origins=None, raises=True): Moved from :mod:`pyramid.session` to :mod:`pyramid.csrf` """ + def _fail(reason): if raises: raise BadCSRFOrigin(reason) @@ -315,7 +317,8 @@ def check_csrf_origin(request, trusted_origins=None, raises=True): if trusted_origins is None: trusted_origins = aslist( request.registry.settings.get( - "pyramid.csrf_trusted_origins", []) + "pyramid.csrf_trusted_origins", [] + ) ) if request.host_port not in set(["80", "443"]): @@ -325,8 +328,9 @@ def check_csrf_origin(request, trusted_origins=None, raises=True): # Actually check to see if the request's origin matches any of our # trusted origins. - if not any(is_same_domain(originp.netloc, host) - for host in trusted_origins): + if not any( + is_same_domain(originp.netloc, host) for host in trusted_origins + ): reason = ( "Referer checking failed - {0} does not match any trusted " "origins." diff --git a/src/pyramid/decorator.py b/src/pyramid/decorator.py index 065a3feed..89cbb0f6e 100644 --- a/src/pyramid/decorator.py +++ b/src/pyramid/decorator.py @@ -32,6 +32,7 @@ class reify(object): >>> f.jammy 2 """ + def __init__(self, wrapped): self.wrapped = wrapped update_wrapper(self, wrapped) @@ -42,4 +43,3 @@ class reify(object): val = self.wrapped(inst) setattr(inst, self.wrapped.__name__, val) return val - diff --git a/src/pyramid/encode.py b/src/pyramid/encode.py index 73ff14e62..2cf2247da 100644 --- a/src/pyramid/encode.py +++ b/src/pyramid/encode.py @@ -4,9 +4,10 @@ from pyramid.compat import ( is_nonstr_iter, url_quote as _url_quote, url_quote_plus as _quote_plus, - ) +) -def url_quote(val, safe=''): # bw compat api + +def url_quote(val, safe=''): # bw compat api cls = val.__class__ if cls is text_type: val = val.encode('utf-8') @@ -14,6 +15,7 @@ def url_quote(val, safe=''): # bw compat api val = str(val).encode('utf-8') return _url_quote(val, safe=safe) + # bw compat api (dnr) def quote_plus(val, safe=''): cls = val.__class__ @@ -23,6 +25,7 @@ def quote_plus(val, safe=''): val = str(val).encode('utf-8') return _quote_plus(val, safe=safe) + def urlencode(query, doseq=True, quote_via=quote_plus): """ An alternate implementation of Python's stdlib diff --git a/src/pyramid/events.py b/src/pyramid/events.py index 93fc127a1..fb3730f63 100644 --- a/src/pyramid/events.py +++ b/src/pyramid/events.py @@ -1,9 +1,6 @@ import venusian -from zope.interface import ( - implementer, - Interface - ) +from zope.interface import implementer, Interface from pyramid.interfaces import ( IContextFound, @@ -12,7 +9,8 @@ from pyramid.interfaces import ( IApplicationCreated, IBeforeRender, IBeforeTraversal, - ) +) + class subscriber(object): """ Decorator activated via a :term:`scan` which treats the function @@ -89,7 +87,8 @@ class subscriber(object): Added the ``_depth`` and ``_category`` arguments. """ - venusian = venusian # for unit testing + + venusian = venusian # for unit testing def __init__(self, *ifaces, **predicates): self.ifaces = ifaces @@ -103,10 +102,15 @@ class subscriber(object): config.add_subscriber(wrapped, iface, **self.predicates) def __call__(self, wrapped): - self.venusian.attach(wrapped, self.register, category=self.category, - depth=self.depth + 1) + self.venusian.attach( + wrapped, + self.register, + category=self.category, + depth=self.depth + 1, + ) return wrapped + @implementer(INewRequest) class NewRequest(object): """ An instance of this class is emitted as an :term:`event` @@ -114,9 +118,11 @@ class NewRequest(object): event instance has an attribute, ``request``, which is a :term:`request` object. This event class implements the :class:`pyramid.interfaces.INewRequest` interface.""" + def __init__(self, request): self.request = request + @implementer(INewResponse) class NewResponse(object): """ An instance of this class is emitted as an :term:`event` @@ -149,10 +155,12 @@ class NewResponse(object): almost purely for symmetry with the :class:`pyramid.interfaces.INewRequest` event. """ + def __init__(self, request, response): self.request = request self.response = response + @implementer(IBeforeTraversal) class BeforeTraversal(object): """ @@ -173,6 +181,7 @@ class BeforeTraversal(object): def __init__(self, request): self.request = request + @implementer(IContextFound) class ContextFound(object): """ An instance of this class is emitted as an :term:`event` after @@ -194,10 +203,13 @@ class ContextFound(object): As of :app:`Pyramid` 1.0, for backwards compatibility purposes, this event may also be imported as :class:`pyramid.events.AfterTraversal`. """ + def __init__(self, request): self.request = request -AfterTraversal = ContextFound # b/c as of 1.0 + +AfterTraversal = ContextFound # b/c as of 1.0 + @implementer(IApplicationCreated) class ApplicationCreated(object): @@ -214,11 +226,14 @@ class ApplicationCreated(object): :class:`pyramid.events.WSGIApplicationCreatedEvent`. This was the name of the event class before :app:`Pyramid` 1.0. """ + def __init__(self, app): self.app = app self.object = app -WSGIApplicationCreatedEvent = ApplicationCreated # b/c (as of 1.0) + +WSGIApplicationCreatedEvent = ApplicationCreated # b/c (as of 1.0) + @implementer(IBeforeRender) class BeforeRender(dict): @@ -283,7 +298,7 @@ class BeforeRender(dict): See also :class:`pyramid.interfaces.IBeforeRender`. """ + def __init__(self, system, rendering_val=None): dict.__init__(self, system) self.rendering_val = rendering_val - diff --git a/src/pyramid/exceptions.py b/src/pyramid/exceptions.py index c95922eb0..9a7054731 100644 --- a/src/pyramid/exceptions.py +++ b/src/pyramid/exceptions.py @@ -1,11 +1,7 @@ -from pyramid.httpexceptions import ( - HTTPBadRequest, - HTTPNotFound, - HTTPForbidden, - ) +from pyramid.httpexceptions import HTTPBadRequest, HTTPNotFound, HTTPForbidden -NotFound = HTTPNotFound # bw compat -Forbidden = HTTPForbidden # bw compat +NotFound = HTTPNotFound # bw compat +Forbidden = HTTPForbidden # bw compat CR = '\n' @@ -15,6 +11,7 @@ class BadCSRFOrigin(HTTPBadRequest): This exception indicates the request has failed cross-site request forgery origin validation. """ + title = "Bad CSRF Origin" explanation = ( "Access is denied. This server can not verify that the origin or " @@ -29,6 +26,7 @@ class BadCSRFToken(HTTPBadRequest): This exception indicates the request has failed cross-site request forgery token validation. """ + title = 'Bad CSRF Token' explanation = ( 'Access is denied. This server can not verify that your cross-site ' @@ -36,7 +34,9 @@ class BadCSRFToken(HTTPBadRequest): 'supplied the wrong cross-site request forgery token or your session ' 'no longer exists. This may be due to session timeout or because ' 'browser is not supplying the credentials required, as can happen ' - 'when the browser has cookies turned off.') + 'when the browser has cookies turned off.' + ) + class PredicateMismatch(HTTPNotFound): """ @@ -65,6 +65,7 @@ class PredicateMismatch(HTTPNotFound): exception view. """ + class URLDecodeError(UnicodeDecodeError): """ This exception is raised when :app:`Pyramid` cannot @@ -76,10 +77,12 @@ class URLDecodeError(UnicodeDecodeError): decoded. """ + class ConfigurationError(Exception): """ Raised when inappropriate input values are supplied to an API method of a :term:`Configurator`""" + class ConfigurationConflictError(ConfigurationError): """ Raised when a configuration conflict is detected during action processing""" @@ -91,7 +94,7 @@ class ConfigurationConflictError(ConfigurationError): r = ["Conflicting configuration actions"] items = sorted(self._conflicts.items()) for discriminator, infos in items: - r.append(" For: %s" % (discriminator, )) + r.append(" For: %s" % (discriminator,)) for info in infos: for line in str(info).rstrip().split(CR): r.append(" " + line) @@ -113,6 +116,7 @@ class ConfigurationExecutionError(ConfigurationError): class CyclicDependencyError(Exception): """ The exception raised when the Pyramid topological sorter detects a cyclic dependency.""" + def __init__(self, cycles): self.cycles = cycles diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py index bef8420b1..359601399 100644 --- a/src/pyramid/httpexceptions.py +++ b/src/pyramid/httpexceptions.py @@ -137,16 +137,12 @@ 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 class_types, text_type, binary_type, text_ from pyramid.interfaces import IExceptionResponse from pyramid.response import Response + def _no_escape(value): if value is None: return '' @@ -159,6 +155,7 @@ def _no_escape(value): value = text_type(value) return value + @implementer(IExceptionResponse) class HTTPException(Response, Exception): @@ -195,18 +192,23 @@ class HTTPException(Response, Exception): code = 520 title = 'Unknown Error' explanation = '' - body_template_obj = Template('''\ + body_template_obj = Template( + '''\ ${explanation}${br}${br} ${detail} ${html_comment} -''') +''' + ) - plain_template_obj = Template('''\ + plain_template_obj = Template( + '''\ ${status} -${body}''') +${body}''' + ) - html_template_obj = Template('''\ + html_template_obj = Template( + '''\ <html> <head> <title>${status}</title> @@ -215,13 +217,21 @@ ${body}''') <h1>${status}</h1> ${body} </body> -</html>''') +</html>''' + ) ## Set this to True for responses that should have no request body empty_body = False - def __init__(self, detail=None, headers=None, comment=None, - body_template=None, json_formatter=None, **kw): + def __init__( + self, + detail=None, + headers=None, + comment=None, + body_template=None, + json_formatter=None, + **kw + ): status = '%s %s' % (self.code, self.title) Response.__init__(self, status=status, **kw) Exception.__init__(self, detail) @@ -243,9 +253,7 @@ ${body}''') return str(self.detail) if self.detail else self.explanation def _json_formatter(self, status, body, title, environ): - return {'message': body, - 'code': status, - 'title': self.title} + return {'message': body, 'code': status, 'title': self.title} def prepare(self, environ): if not self.has_body and not self.empty_body: @@ -255,7 +263,9 @@ ${body}''') accept = create_accept_header(accept_value) # Attempt to match text/html or application/json, if those don't # match, we will fall through to defaulting to text/plain - acceptable = accept.acceptable_offers(['text/html', 'application/json']) + acceptable = accept.acceptable_offers( + ['text/html', 'application/json'] + ) acceptable = [offer[0] for offer in acceptable] + ['text/plain'] match = acceptable[0] @@ -281,8 +291,10 @@ ${body}''') def substitute(self, status, body): jsonbody = self.excobj._json_formatter( status=status, - body=body, title=self.excobj.title, - environ=environ) + body=body, + title=self.excobj.title, + environ=environ, + ) return json.dumps(jsonbody) page_template = JsonPageTemplate(self) @@ -299,7 +311,7 @@ ${body}''') 'detail': escape(self.detail or ''), 'comment': escape(comment), 'html_comment': html_comment, - } + } body_tmpl = self.body_template_obj if HTTPException.body_template_obj is not body_tmpl: # Custom template; add headers to args @@ -324,7 +336,7 @@ ${body}''') # bw compat only return self - exception = wsgi_response # bw compat only + exception = wsgi_response # bw compat only def __call__(self, environ, start_response): # differences from webob.exc.WSGIHTTPException @@ -337,7 +349,9 @@ ${body}''') self.prepare(environ) return Response.__call__(self, environ, start_response) -WSGIHTTPException = HTTPException # b/c post 1.5 + +WSGIHTTPException = HTTPException # b/c post 1.5 + class HTTPError(HTTPException): """ @@ -347,6 +361,7 @@ class HTTPError(HTTPException): and that any work in progress should not be committed. """ + class HTTPRedirection(HTTPException): """ base class for exceptions with status codes in the 300s (redirections) @@ -357,16 +372,19 @@ class HTTPRedirection(HTTPException): condition. """ + class HTTPSuccessful(HTTPException): """ Base class for exceptions with status codes in the 200s (successful responses) """ + ############################################################ ## 2xx success ############################################################ + class HTTPOk(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -375,9 +393,11 @@ class HTTPOk(HTTPSuccessful): code: 200, title: OK """ + code = 200 title = 'OK' + class HTTPCreated(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -387,9 +407,11 @@ class HTTPCreated(HTTPSuccessful): code: 201, title: Created """ + code = 201 title = 'Created' + class HTTPAccepted(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -399,10 +421,12 @@ class HTTPAccepted(HTTPSuccessful): code: 202, title: Accepted """ + code = 202 title = 'Accepted' explanation = 'The request is accepted for processing.' + class HTTPNonAuthoritativeInformation(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -413,9 +437,11 @@ class HTTPNonAuthoritativeInformation(HTTPSuccessful): code: 203, title: Non-Authoritative Information """ + code = 203 title = 'Non-Authoritative Information' + class HTTPNoContent(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -426,10 +452,12 @@ class HTTPNoContent(HTTPSuccessful): code: 204, title: No Content """ + code = 204 title = 'No Content' empty_body = True + class HTTPResetContent(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -440,10 +468,12 @@ class HTTPResetContent(HTTPSuccessful): code: 205, title: Reset Content """ + code = 205 title = 'Reset Content' empty_body = True + class HTTPPartialContent(HTTPSuccessful): """ subclass of :class:`~HTTPSuccessful` @@ -453,15 +483,18 @@ class HTTPPartialContent(HTTPSuccessful): code: 206, title: Partial Content """ + code = 206 title = 'Partial Content' + ## FIXME: add 207 Multi-Status (but it's complicated) ############################################################ ## 3xx redirection ############################################################ + class _HTTPMove(HTTPRedirection): """ redirections which require a Location field @@ -472,6 +505,7 @@ class _HTTPMove(HTTPRedirection): You must provide a ``location`` keyword argument. """ + # differences from webob.exc._HTTPMove: # # - ${location} isn't wrapped in an <a> tag in body @@ -486,18 +520,33 @@ class _HTTPMove(HTTPRedirection): # - ``add_slash`` argument is no longer accepted: code that passes # add_slash argument to the constructor will receive an exception. explanation = 'The resource has been moved to' - body_template_obj = Template('''\ + body_template_obj = Template( + '''\ ${explanation} ${location}; you should be redirected automatically. ${detail} -${html_comment}''') +${html_comment}''' + ) - def __init__(self, location='', detail=None, headers=None, comment=None, - body_template=None, **kw): + def __init__( + self, + location='', + detail=None, + headers=None, + comment=None, + body_template=None, + **kw + ): if location is None: raise ValueError("HTTP redirects need a location to redirect to.") super(_HTTPMove, self).__init__( - detail=detail, headers=headers, comment=comment, - body_template=body_template, location=location, **kw) + detail=detail, + headers=headers, + comment=comment, + body_template=body_template, + location=location, + **kw + ) + class HTTPMultipleChoices(_HTTPMove): """ @@ -511,9 +560,11 @@ class HTTPMultipleChoices(_HTTPMove): code: 300, title: Multiple Choices """ + code = 300 title = 'Multiple Choices' + class HTTPMovedPermanently(_HTTPMove): """ subclass of :class:`~_HTTPMove` @@ -524,9 +575,11 @@ class HTTPMovedPermanently(_HTTPMove): code: 301, title: Moved Permanently """ + code = 301 title = 'Moved Permanently' + class HTTPFound(_HTTPMove): """ subclass of :class:`~_HTTPMove` @@ -536,10 +589,12 @@ class HTTPFound(_HTTPMove): code: 302, title: Found """ + code = 302 title = 'Found' explanation = 'The resource was found at' + # This one is safe after a POST (the redirected location will be # retrieved with GET): class HTTPSeeOther(_HTTPMove): @@ -552,9 +607,11 @@ class HTTPSeeOther(_HTTPMove): code: 303, title: See Other """ + code = 303 title = 'See Other' + class HTTPNotModified(HTTPRedirection): """ subclass of :class:`~HTTPRedirection` @@ -565,11 +622,13 @@ class HTTPNotModified(HTTPRedirection): code: 304, title: Not Modified """ + # FIXME: this should include a date or etag header code = 304 title = 'Not Modified' empty_body = True + class HTTPUseProxy(_HTTPMove): """ subclass of :class:`~_HTTPMove` @@ -579,11 +638,12 @@ class HTTPUseProxy(_HTTPMove): code: 305, title: Use Proxy """ + # Not a move, but looks a little like one code = 305 title = 'Use Proxy' - explanation = ( - 'The resource must be accessed through a proxy located at') + explanation = 'The resource must be accessed through a proxy located at' + class HTTPTemporaryRedirect(_HTTPMove): """ @@ -594,9 +654,11 @@ class HTTPTemporaryRedirect(_HTTPMove): code: 307, title: Temporary Redirect """ + code = 307 title = 'Temporary Redirect' + class HTTPPermanentRedirect(_HTTPMove): """ subclass of :class:`~_HTTPMove` @@ -607,13 +669,16 @@ class HTTPPermanentRedirect(_HTTPMove): code: 308, title: Permanent Redirect """ + code = 308 title = 'Permanent Redirect' + ############################################################ ## 4xx client error ############################################################ + class HTTPClientError(HTTPError): """ base class for the 400s, where the client is in error @@ -623,9 +688,11 @@ class HTTPClientError(HTTPError): a bug. A server-side traceback is not warranted. Unless specialized, this is a '400 Bad Request' """ + code = 400 title = 'Bad Request' + class HTTPBadRequest(HTTPClientError): """ subclass of :class:`~HTTPClientError` @@ -635,8 +702,12 @@ class HTTPBadRequest(HTTPClientError): code: 400, title: Bad Request """ - explanation = ('The server could not comply with the request since ' - 'it is either malformed or otherwise incorrect.') + + explanation = ( + 'The server could not comply with the request since ' + 'it is either malformed or otherwise incorrect.' + ) + class HTTPUnauthorized(HTTPClientError): """ @@ -646,13 +717,16 @@ class HTTPUnauthorized(HTTPClientError): code: 401, title: Unauthorized """ + code = 401 title = 'Unauthorized' explanation = ( 'This server could not verify that you are authorized to ' 'access the document you requested. Either you supplied the ' 'wrong credentials (e.g., bad password), or your browser ' - 'does not understand how to supply the credentials required.') + 'does not understand how to supply the credentials required.' + ) + class HTTPPaymentRequired(HTTPClientError): """ @@ -660,9 +734,11 @@ class HTTPPaymentRequired(HTTPClientError): code: 402, title: Payment Required """ + code = 402 title = 'Payment Required' - explanation = ('Access was denied for financial reasons.') + explanation = 'Access was denied for financial reasons.' + class HTTPForbidden(HTTPClientError): """ @@ -693,6 +769,7 @@ class HTTPForbidden(HTTPClientError): exception as necessary to provide extended information in an error report shown to a user. """ + # differences from webob.exc.HTTPForbidden: # # - accepts a ``result`` keyword argument @@ -705,14 +782,28 @@ class HTTPForbidden(HTTPClientError): # code = 403 title = 'Forbidden' - explanation = ('Access was denied to this resource.') - def __init__(self, detail=None, headers=None, comment=None, - body_template=None, result=None, **kw): - HTTPClientError.__init__(self, detail=detail, headers=headers, - comment=comment, body_template=body_template, - **kw) + explanation = 'Access was denied to this resource.' + + def __init__( + self, + detail=None, + headers=None, + comment=None, + body_template=None, + result=None, + **kw + ): + HTTPClientError.__init__( + self, + detail=detail, + headers=headers, + comment=comment, + body_template=body_template, + **kw + ) self.result = result + class HTTPNotFound(HTTPClientError): """ subclass of :class:`~HTTPClientError` @@ -732,9 +823,11 @@ class HTTPNotFound(HTTPClientError): string will be available as the ``message`` attribute of this exception, for availability to the :term:`Not Found View`. """ + code = 404 title = 'Not Found' - explanation = ('The resource could not be found.') + explanation = 'The resource could not be found.' + class HTTPMethodNotAllowed(HTTPClientError): """ @@ -745,14 +838,18 @@ class HTTPMethodNotAllowed(HTTPClientError): code: 405, title: Method Not Allowed """ + # differences from webob.exc.HTTPMethodNotAllowed: # # - body_template_obj uses ${br} instead of <br /> code = 405 title = 'Method Not Allowed' - body_template_obj = Template('''\ + body_template_obj = Template( + '''\ The method ${REQUEST_METHOD} is not allowed for this resource. ${br}${br} -${detail}''') +${detail}''' + ) + class HTTPNotAcceptable(HTTPClientError): """ @@ -765,12 +862,14 @@ class HTTPNotAcceptable(HTTPClientError): code: 406, title: Not Acceptable """ + # differences from webob.exc.HTTPNotAcceptable: # # - "template" attribute left off (useless, bug in webob?) code = 406 title = 'Not Acceptable' + class HTTPProxyAuthenticationRequired(HTTPClientError): """ subclass of :class:`~HTTPClientError` @@ -780,9 +879,11 @@ class HTTPProxyAuthenticationRequired(HTTPClientError): code: 407, title: Proxy Authentication Required """ + code = 407 title = 'Proxy Authentication Required' - explanation = ('Authentication with a local proxy is needed.') + explanation = 'Authentication with a local proxy is needed.' + class HTTPRequestTimeout(HTTPClientError): """ @@ -793,10 +894,14 @@ class HTTPRequestTimeout(HTTPClientError): code: 408, title: Request Timeout """ + code = 408 title = 'Request Timeout' - explanation = ('The server has waited too long for the request to ' - 'be sent by the client.') + explanation = ( + 'The server has waited too long for the request to ' + 'be sent by the client.' + ) + class HTTPConflict(HTTPClientError): """ @@ -807,10 +912,13 @@ class HTTPConflict(HTTPClientError): code: 409, title: Conflict """ + code = 409 title = 'Conflict' - explanation = ('There was a conflict when trying to complete ' - 'your request.') + explanation = ( + 'There was a conflict when trying to complete ' 'your request.' + ) + class HTTPGone(HTTPClientError): """ @@ -821,10 +929,14 @@ class HTTPGone(HTTPClientError): code: 410, title: Gone """ + code = 410 title = 'Gone' - explanation = ('This resource is no longer available. No forwarding ' - 'address is given.') + explanation = ( + 'This resource is no longer available. No forwarding ' + 'address is given.' + ) + class HTTPLengthRequired(HTTPClientError): """ @@ -835,9 +947,11 @@ class HTTPLengthRequired(HTTPClientError): code: 411, title: Length Required """ + code = 411 title = 'Length Required' - explanation = ('Content-Length header required.') + explanation = 'Content-Length header required.' + class HTTPPreconditionFailed(HTTPClientError): """ @@ -849,9 +963,11 @@ class HTTPPreconditionFailed(HTTPClientError): code: 412, title: Precondition Failed """ + code = 412 title = 'Precondition Failed' - explanation = ('Request precondition failed.') + explanation = 'Request precondition failed.' + class HTTPRequestEntityTooLarge(HTTPClientError): """ @@ -863,9 +979,11 @@ class HTTPRequestEntityTooLarge(HTTPClientError): code: 413, title: Request Entity Too Large """ + code = 413 title = 'Request Entity Too Large' - explanation = ('The body of your request was too large for this server.') + explanation = 'The body of your request was too large for this server.' + class HTTPRequestURITooLong(HTTPClientError): """ @@ -877,9 +995,11 @@ class HTTPRequestURITooLong(HTTPClientError): code: 414, title: Request-URI Too Long """ + code = 414 title = 'Request-URI Too Long' - explanation = ('The request URI was too long for this server.') + explanation = 'The request URI was too long for this server.' + class HTTPUnsupportedMediaType(HTTPClientError): """ @@ -891,12 +1011,14 @@ class HTTPUnsupportedMediaType(HTTPClientError): code: 415, title: Unsupported Media Type """ + # differences from webob.exc.HTTPUnsupportedMediaType: # # - "template_obj" attribute left off (useless, bug in webob?) code = 415 title = 'Unsupported Media Type' + class HTTPRequestRangeNotSatisfiable(HTTPClientError): """ subclass of :class:`~HTTPClientError` @@ -909,9 +1031,11 @@ class HTTPRequestRangeNotSatisfiable(HTTPClientError): code: 416, title: Request Range Not Satisfiable """ + code = 416 title = 'Request Range Not Satisfiable' - explanation = ('The Range requested is not available.') + explanation = 'The Range requested is not available.' + class HTTPExpectationFailed(HTTPClientError): """ @@ -922,9 +1046,11 @@ class HTTPExpectationFailed(HTTPClientError): code: 417, title: Expectation Failed """ + code = 417 title = 'Expectation Failed' - explanation = ('Expectation failed.') + explanation = 'Expectation failed.' + class HTTPUnprocessableEntity(HTTPClientError): """ @@ -940,11 +1066,13 @@ class HTTPUnprocessableEntity(HTTPClientError): code: 422, title: Unprocessable Entity """ + ## Note: from WebDAV code = 422 title = 'Unprocessable Entity' explanation = 'Unable to process the contained instructions' + class HTTPLocked(HTTPClientError): """ subclass of :class:`~HTTPClientError` @@ -953,10 +1081,12 @@ class HTTPLocked(HTTPClientError): code: 423, title: Locked """ + ## Note: from WebDAV code = 423 title = 'Locked' - explanation = ('The resource is locked') + explanation = 'The resource is locked' + class HTTPFailedDependency(HTTPClientError): """ @@ -967,12 +1097,15 @@ class HTTPFailedDependency(HTTPClientError): code: 424, title: Failed Dependency """ + ## Note: from WebDAV code = 424 title = 'Failed Dependency' explanation = ( 'The method could not be performed because the requested ' - 'action dependended on another action and that action failed') + 'action dependended on another action and that action failed' + ) + class HTTPPreconditionRequired(HTTPClientError): """ @@ -991,10 +1124,11 @@ class HTTPPreconditionRequired(HTTPClientError): code: 428, title: Precondition Required """ + code = 428 title = 'Precondition Required' - explanation = ( - 'The origin server requires the request to be conditional.') + explanation = 'The origin server requires the request to be conditional.' + class HTTPTooManyRequests(HTTPClientError): """ @@ -1007,11 +1141,14 @@ class HTTPTooManyRequests(HTTPClientError): code: 429, title: Too Many Requests """ + code = 429 title = 'Too Many Requests' explanation = ( 'The action could not be performed because there were too ' - 'many requests by the client.') + 'many requests by the client.' + ) + class HTTPRequestHeaderFieldsTooLarge(HTTPClientError): """ @@ -1025,10 +1162,11 @@ class HTTPRequestHeaderFieldsTooLarge(HTTPClientError): code: 431, title: Request Header Fields Too Large """ + code = 431 title = 'Request Header Fields Too Large' - explanation = ( - 'The requests header fields were too large.') + explanation = 'The requests header fields were too large.' + ############################################################ ## 5xx Server Error @@ -1041,6 +1179,7 @@ class HTTPRequestHeaderFieldsTooLarge(HTTPClientError): # agents SHOULD display any included entity to the user. These response # codes are applicable to any request method. + class HTTPServerError(HTTPError): """ base class for the 500s, where the server is in-error @@ -1048,9 +1187,11 @@ class HTTPServerError(HTTPError): This is an error condition in which the server is presumed to be in-error. Unless specialized, this is a '500 Internal Server Error'. """ + code = 500 title = 'Internal Server Error' + class HTTPInternalServerError(HTTPServerError): """ subclass of :class:`~HTTPServerError` @@ -1060,9 +1201,12 @@ class HTTPInternalServerError(HTTPServerError): code: 500, title: Internal Server Error """ + explanation = ( 'The server has either erred or is incapable of performing ' - 'the requested operation.') + 'the requested operation.' + ) + class HTTPNotImplemented(HTTPServerError): """ @@ -1073,12 +1217,14 @@ class HTTPNotImplemented(HTTPServerError): code: 501, title: Not Implemented """ + # differences from webob.exc.HTTPNotAcceptable: # # - "template" attr left off (useless, bug in webob?) code = 501 title = 'Not Implemented' + class HTTPBadGateway(HTTPServerError): """ subclass of :class:`~HTTPServerError` @@ -1089,9 +1235,11 @@ class HTTPBadGateway(HTTPServerError): code: 502, title: Bad Gateway """ + code = 502 title = 'Bad Gateway' - explanation = ('Bad gateway.') + explanation = 'Bad gateway.' + class HTTPServiceUnavailable(HTTPServerError): """ @@ -1102,10 +1250,14 @@ class HTTPServiceUnavailable(HTTPServerError): code: 503, title: Service Unavailable """ + code = 503 title = 'Service Unavailable' - explanation = ('The server is currently unavailable. ' - 'Please try again at a later time.') + explanation = ( + 'The server is currently unavailable. ' + 'Please try again at a later time.' + ) + class HTTPGatewayTimeout(HTTPServerError): """ @@ -1118,9 +1270,11 @@ class HTTPGatewayTimeout(HTTPServerError): code: 504, title: Gateway Timeout """ + code = 504 title = 'Gateway Timeout' - explanation = ('The gateway has timed out.') + explanation = 'The gateway has timed out.' + class HTTPVersionNotSupported(HTTPServerError): """ @@ -1132,9 +1286,11 @@ class HTTPVersionNotSupported(HTTPServerError): code: 505, title: HTTP Version Not Supported """ + code = 505 title = 'HTTP Version Not Supported' - explanation = ('The HTTP version is not supported.') + explanation = 'The HTTP version is not supported.' + class HTTPInsufficientStorage(HTTPServerError): """ @@ -1145,9 +1301,11 @@ class HTTPInsufficientStorage(HTTPServerError): code: 507, title: Insufficient Storage """ + code = 507 title = 'Insufficient Storage' - explanation = ('There was not enough space to save the resource') + explanation = 'There was not enough space to save the resource' + def exception_response(status_code, **kw): """Creates an HTTP exception based on a status code. Example:: @@ -1159,22 +1317,24 @@ def exception_response(status_code, **kw): exc = status_map[status_code](**kw) return exc + def default_exceptionresponse_view(context, request): if not isinstance(context, Exception): # backwards compat for an exception response view registered via # config.set_notfound_view or config.set_forbidden_view # instead of as a proper exception view context = request.exception or context - return context # assumed to be an IResponse + return context # assumed to be an IResponse + status_map = {} code = None for name, value in list(globals().items()): if ( - isinstance(value, class_types) and - issubclass(value, HTTPException) and - value not in {HTTPClientError, HTTPServerError} and - not name.startswith('_') + isinstance(value, class_types) + and issubclass(value, HTTPException) + and value not in {HTTPClientError, HTTPServerError} + and not name.startswith('_') ): code = getattr(value, 'code', None) if code: diff --git a/src/pyramid/i18n.py b/src/pyramid/i18n.py index 1d11adfe3..9f5f898be 100644 --- a/src/pyramid/i18n.py +++ b/src/pyramid/i18n.py @@ -4,9 +4,9 @@ import os from translationstring import ( Translator, Pluralizer, - TranslationString, # API - TranslationStringFactory, # API - ) + TranslationString, # API + TranslationStringFactory, # API +) from pyramid.compat import PY2 from pyramid.decorator import reify @@ -15,7 +15,7 @@ from pyramid.interfaces import ( ILocalizer, ITranslationDirectories, ILocaleNegotiator, - ) +) from pyramid.threadlocal import get_current_registry @@ -24,6 +24,7 @@ TranslationStringFactory = TranslationStringFactory # PyFlakes DEFAULT_PLURAL = lambda n: int(n != 1) + class Localizer(object): """ An object providing translation and pluralizations related to @@ -31,6 +32,7 @@ class Localizer(object): :class:`pyramid.i18n.Localizer` object is created using the :func:`pyramid.i18n.get_localizer` function. """ + def __init__(self, locale_name, translations): self.locale_name = locale_name self.translations = translations @@ -112,8 +114,9 @@ class Localizer(object): """ if self.pluralizer is None: self.pluralizer = Pluralizer(self.translations) - return self.pluralizer(singular, plural, n, domain=domain, - mapping=mapping) + return self.pluralizer( + singular, plural, n, domain=domain, mapping=mapping + ) def default_locale_negotiator(request): @@ -142,6 +145,7 @@ def default_locale_negotiator(request): locale_name = request.cookies.get(name) return locale_name + def negotiate_locale_name(request): """ Negotiate and return the :term:`locale name` associated with the current request.""" @@ -149,8 +153,9 @@ def negotiate_locale_name(request): registry = request.registry except AttributeError: registry = get_current_registry() - negotiator = registry.queryUtility(ILocaleNegotiator, - default=default_locale_negotiator) + negotiator = registry.queryUtility( + ILocaleNegotiator, default=default_locale_negotiator + ) locale_name = negotiator(request) if locale_name is None: @@ -159,6 +164,7 @@ def negotiate_locale_name(request): return locale_name + def get_locale_name(request): """ .. deprecated:: 1.5 @@ -167,6 +173,7 @@ def get_locale_name(request): """ return request.locale_name + def make_localizer(current_locale_name, translation_directories): """ Create a :class:`pyramid.i18n.Localizer` object corresponding to the provided locale name from the @@ -199,16 +206,17 @@ def make_localizer(current_locale_name, translation_directories): if not os.path.isdir(os.path.realpath(messages_dir)): continue for mofile in os.listdir(messages_dir): - mopath = os.path.realpath(os.path.join(messages_dir, - mofile)) + mopath = os.path.realpath(os.path.join(messages_dir, mofile)) if mofile.endswith('.mo') and os.path.isfile(mopath): with open(mopath, 'rb') as mofp: domain = mofile[:-3] dtrans = Translations(mofp, domain) translations.add(dtrans) - return Localizer(locale_name=current_locale_name, - translations=translations) + return Localizer( + locale_name=current_locale_name, translations=translations + ) + def get_localizer(request): """ @@ -219,6 +227,7 @@ def get_localizer(request): """ return request.localizer + class Translations(gettext.GNUTranslations, object): """An extended translation catalog class (ripped off from Babel) """ @@ -272,8 +281,10 @@ class Translations(gettext.GNUTranslations, object): return cls(fileobj=fp, domain=domain) def __repr__(self): - return '<%s: "%s">' % (type(self).__name__, - self._info.get('project-id-version')) + return '<%s: "%s">' % ( + type(self).__name__, + self._info.get('project-id-version'), + ) def add(self, translations, merge=True): """Add the given translations to the catalog. @@ -331,13 +342,13 @@ class Translations(gettext.GNUTranslations, object): domain. """ return self._domains.get(domain, self).gettext(message) - + def ldgettext(self, domain, message): """Like ``lgettext()``, but look the message up in the specified domain. - """ + """ return self._domains.get(domain, self).lgettext(message) - + def dugettext(self, domain, message): """Like ``ugettext()``, but look the message up in the specified domain. @@ -346,29 +357,32 @@ class Translations(gettext.GNUTranslations, object): return self._domains.get(domain, self).ugettext(message) else: 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 domain. """ return self._domains.get(domain, self).ngettext(singular, plural, num) - + def ldngettext(self, domain, singular, plural, num): """Like ``lngettext()``, but look the message up in the specified domain. """ return self._domains.get(domain, self).lngettext(singular, plural, num) - + def dungettext(self, domain, singular, plural, num): """Like ``ungettext()`` but look the message up in the specified domain. """ if PY2: return self._domains.get(domain, self).ungettext( - singular, plural, num) + singular, plural, num + ) else: return self._domains.get(domain, self).ngettext( - singular, plural, num) + singular, plural, num + ) + class LocalizerRequestMixin(object): @reify @@ -384,8 +398,9 @@ class LocalizerRequestMixin(object): tdirs = registry.queryUtility(ITranslationDirectories, default=[]) localizer = make_localizer(current_locale_name, tdirs) - registry.registerUtility(localizer, ILocalizer, - name=current_locale_name) + registry.registerUtility( + localizer, ILocalizer, name=current_locale_name + ) return localizer @@ -393,5 +408,3 @@ class LocalizerRequestMixin(object): def locale_name(self): locale_name = negotiate_locale_name(self) return locale_name - - diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py index 4df5593f8..26a9d7025 100644 --- a/src/pyramid/interfaces.py +++ b/src/pyramid/interfaces.py @@ -1,14 +1,12 @@ from zope.deprecation import deprecated -from zope.interface import ( - Attribute, - Interface, - ) +from zope.interface import Attribute, Interface from pyramid.compat import PY2 # public API interfaces + class IContextFound(Interface): """ An event type that is emitted after :app:`Pyramid` finds a :term:`context` object but before it calls any view code. See the @@ -21,32 +19,41 @@ class IContextFound(Interface): :app:`Pyramid` before 1.0, this event interface can also be imported as :class:`pyramid.interfaces.IAfterTraversal`. """ + request = Attribute('The request object') + IAfterTraversal = IContextFound + class IBeforeTraversal(Interface): """ An event type that is emitted after :app:`Pyramid` attempted to find a route but before it calls any traversal or view code. See the documentation attached to :class:`pyramid.events.Routefound` for more information. """ + request = Attribute('The request object') + class INewRequest(Interface): """ An event type that is emitted whenever :app:`Pyramid` begins to process a new request. See the documentation attached to :class:`pyramid.events.NewRequest` for more information.""" + request = Attribute('The request object') + class INewResponse(Interface): """ An event type that is emitted whenever any :app:`Pyramid` view returns a response. See the documentation attached to :class:`pyramid.events.NewResponse` for more information.""" + request = Attribute('The request object') response = Attribute('The response object') + class IApplicationCreated(Interface): """ Event issued when the :meth:`pyramid.config.Configurator.make_wsgi_app` method @@ -60,9 +67,12 @@ class IApplicationCreated(Interface): versions before 1.0, this interface can also be imported as :class:`pyramid.interfaces.IWSGIApplicationCreatedEvent`. """ + app = Attribute("Created application") -IWSGIApplicationCreatedEvent = IApplicationCreated # b /c + +IWSGIApplicationCreatedEvent = IApplicationCreated # b /c + class IResponse(Interface): """ Represents a WSGI response using the WebOb response interface. @@ -74,7 +84,8 @@ class IResponse(Interface): :mod:`pyramid.httpexceptions`.""" RequestClass = Attribute( - """ Alias for :class:`pyramid.request.Request` """) + """ Alias for :class:`pyramid.request.Request` """ + ) def __call__(environ, start_response): """ :term:`WSGI` call interface, should call the start_response @@ -82,21 +93,25 @@ class IResponse(Interface): accept_ranges = Attribute( """Gets and sets and deletes the Accept-Ranges header. For more - information on Accept-Ranges see RFC 2616, section 14.5""") + information on Accept-Ranges see RFC 2616, section 14.5""" + ) age = Attribute( """Gets and sets and deletes the Age header. Converts using int. - For more information on Age see RFC 2616, section 14.6.""") + For more information on Age see RFC 2616, section 14.6.""" + ) allow = Attribute( """Gets and sets and deletes the Allow header. Converts using - list. For more information on Allow see RFC 2616, Section 14.7.""") + list. For more information on Allow see RFC 2616, Section 14.7.""" + ) app_iter = Attribute( """Returns the app_iter of the response. If body was set, this will create an app_iter from that body - (a single-item list)""") + (a single-item list)""" + ) def app_iter_range(start, stop): """ Return a new app_iter built from the response app_iter that @@ -104,21 +119,24 @@ class IResponse(Interface): body = Attribute( """The body of the response, as a str. This will read in the entire - app_iter if necessary.""") + app_iter if necessary.""" + ) body_file = Attribute( """A file-like object that can be used to write to the body. If you - passed in a list app_iter, that app_iter will be modified by writes.""") + passed in a list app_iter, that app_iter will be modified by writes.""" + ) cache_control = Attribute( - """Get/set/modify the Cache-Control header (RFC 2616 section 14.9)""") + """Get/set/modify the Cache-Control header (RFC 2616 section 14.9)""" + ) cache_expires = Attribute( """ Get/set the Cache-Control and Expires headers. This sets the - response to expire in the number of seconds passed when set. """) + response to expire in the number of seconds passed when set. """ + ) - charset = Attribute( - """Get/set the charset (in the Content-Type)""") + charset = Attribute("""Get/set the charset (in the Content-Type)""") def conditional_response_app(environ, start_response): """ Like the normal __call__ interface, but checks conditional @@ -133,52 +151,62 @@ class IResponse(Interface): content_disposition = Attribute( """Gets and sets and deletes the Content-Disposition header. For more information on Content-Disposition see RFC 2616 section - 19.5.1.""") + 19.5.1.""" + ) content_encoding = Attribute( """Gets and sets and deletes the Content-Encoding header. For more - information about Content-Encoding see RFC 2616 section 14.11.""") + information about Content-Encoding see RFC 2616 section 14.11.""" + ) content_language = Attribute( """Gets and sets and deletes the Content-Language header. Converts using list. For more information about Content-Language see RFC 2616 - section 14.12.""") + section 14.12.""" + ) content_length = Attribute( """Gets and sets and deletes the Content-Length header. For more information on Content-Length see RFC 2616 section 14.17. - Converts using int. """) + Converts using int. """ + ) content_location = Attribute( """Gets and sets and deletes the Content-Location header. For more - information on Content-Location see RFC 2616 section 14.14.""") + information on Content-Location see RFC 2616 section 14.14.""" + ) content_md5 = Attribute( """Gets and sets and deletes the Content-MD5 header. For more - information on Content-MD5 see RFC 2616 section 14.14.""") + information on Content-MD5 see RFC 2616 section 14.14.""" + ) content_range = Attribute( """Gets and sets and deletes the Content-Range header. For more information on Content-Range see section 14.16. Converts using - ContentRange object.""") + ContentRange object.""" + ) content_type = Attribute( """Get/set the Content-Type header (or None), without the charset or any parameters. If you include parameters (or ; at all) when setting the content_type, any existing parameters will be deleted; - otherwise they will be preserved.""") + otherwise they will be preserved.""" + ) content_type_params = Attribute( """A dictionary of all the parameters in the content type. This is not a view, set to change, modifications of the dict would not - be applied otherwise.""") + be applied otherwise.""" + ) def copy(): """ Makes a copy of the response and returns the copy. """ date = Attribute( """Gets and sets and deletes the Date header. For more information on - Date see RFC 2616 section 14.18. Converts using HTTP date.""") + Date see RFC 2616 section 14.18. Converts using HTTP date.""" + ) def delete_cookie(name, path='/', domain=None): """ Delete a cookie from the client. Note that path and domain must @@ -191,31 +219,34 @@ class IResponse(Interface): environ = Attribute( """Get/set the request environ associated with this response, - if any.""") + if any.""" + ) etag = Attribute( """ Gets and sets and deletes the ETag header. For more information - on ETag see RFC 2616 section 14.19. Converts using Entity tag.""") + on ETag see RFC 2616 section 14.19. Converts using Entity tag.""" + ) expires = Attribute( """ Gets and sets and deletes the Expires header. For more information on Expires see RFC 2616 section 14.21. Converts using - HTTP date.""") + HTTP date.""" + ) - headerlist = Attribute( - """ The list of response headers. """) + headerlist = Attribute(""" The list of response headers. """) - headers = Attribute( - """ The headers in a dictionary-like object """) + headers = Attribute(""" The headers in a dictionary-like object """) last_modified = Attribute( """ Gets and sets and deletes the Last-Modified header. For more information on Last-Modified see RFC 2616 section 14.29. Converts - using HTTP date.""") + using HTTP date.""" + ) location = Attribute( """ Gets and sets and deletes the Location header. For more - information on Location see RFC 2616 section 14.30.""") + information on Location see RFC 2616 section 14.30.""" + ) def md5_etag(body=None, set_content_md5=False): """ Generate an etag for the response object using an MD5 hash of the @@ -230,34 +261,46 @@ class IResponse(Interface): pragma = Attribute( """ Gets and sets and deletes the Pragma header. For more information - on Pragma see RFC 2616 section 14.32. """) + on Pragma see RFC 2616 section 14.32. """ + ) request = Attribute( - """ Return the request associated with this response if any. """) + """ Return the request associated with this response if any. """ + ) retry_after = Attribute( """ Gets and sets and deletes the Retry-After header. For more information on Retry-After see RFC 2616 section 14.37. Converts - using HTTP date or delta seconds.""") + using HTTP date or delta seconds.""" + ) server = Attribute( """ Gets and sets and deletes the Server header. For more information - on Server see RFC216 section 14.38. """) + on Server see RFC216 section 14.38. """ + ) - def set_cookie(name, value='', max_age=None, path='/', domain=None, - secure=False, httponly=False, comment=None, expires=None, - overwrite=False): + def set_cookie( + name, + value='', + max_age=None, + path='/', + domain=None, + secure=False, + httponly=False, + comment=None, + expires=None, + overwrite=False, + ): """ Set (add) a cookie for the response """ - status = Attribute( - """ The status string. """) + status = Attribute(""" The status string. """) - status_int = Attribute( - """ The status as an integer """) + status_int = Attribute(""" The status as an integer """) unicode_body = Attribute( """ Get/set the unicode value of the body (using the charset of - the Content-Type)""") + the Content-Type)""" + ) def unset_cookie(name, strict=True): """ Unset a cookie with the given name (remove it from the @@ -265,16 +308,20 @@ class IResponse(Interface): vary = Attribute( """Gets and sets and deletes the Vary header. For more information - on Vary see section 14.44. Converts using list.""") + on Vary see section 14.44. Converts using list.""" + ) www_authenticate = Attribute( """ Gets and sets and deletes the WWW-Authenticate header. For more information on WWW-Authenticate see RFC 2616 section 14.47. Converts - using 'parse_auth' and 'serialize_auth'. """) + using 'parse_auth' and 'serialize_auth'. """ + ) + -class IException(Interface): # not an API +class IException(Interface): # not an API """ An interface representing a generic exception """ + class IExceptionResponse(IException, IResponse): """ An interface representing a WSGI response which is also an exception object. Register an exception view using this interface as a ``context`` @@ -283,9 +330,11 @@ class IExceptionResponse(IException, IResponse): :class:`pyramid.response.Response`, including :class:`pyramid.httpexceptions.HTTPNotFound` and :class:`pyramid.httpexceptions.HTTPForbidden`).""" + def prepare(environ): """ Prepares the response for being called as a WSGI application """ + class IDict(Interface): # Documentation-only interface @@ -354,6 +403,7 @@ class IDict(Interface): def clear(): """ Clear all values from the dictionary """ + class IBeforeRender(IDict): """ Subscribers to this event may introspect and modify the set of @@ -373,26 +423,37 @@ class IBeforeRender(IDict): See also :ref:`beforerender_event`. """ - rendering_val = Attribute('The value returned by a view or passed to a ' - '``render`` method for this rendering. ' - 'This feature is new in Pyramid 1.2.') + + rendering_val = Attribute( + 'The value returned by a view or passed to a ' + '``render`` method for this rendering. ' + 'This feature is new in Pyramid 1.2.' + ) + class IRendererInfo(Interface): """ An object implementing this interface is passed to every :term:`renderer factory` constructor as its only argument (conventionally named ``info``)""" + name = Attribute('The value passed by the user as the renderer name') - package = Attribute('The "current package" when the renderer ' - 'configuration statement was found') + package = Attribute( + 'The "current package" when the renderer ' + 'configuration statement was found' + ) type = Attribute('The renderer type name') - registry = Attribute('The "current" application registry when the ' - 'renderer was created') - settings = Attribute('The deployment settings dictionary related ' - 'to the current application') + registry = Attribute( + 'The "current" application registry when the ' 'renderer was created' + ) + settings = Attribute( + 'The deployment settings dictionary related ' + 'to the current application' + ) def clone(): """ Return a shallow copy that does not share any mutable state.""" + class IRendererFactory(Interface): def __call__(info): """ Return an object that implements @@ -400,6 +461,7 @@ class IRendererFactory(Interface): object that implements :class:`pyramid.interfaces.IRendererInfo`. """ + class IRenderer(Interface): def __call__(value, system): """ Call the renderer with the result of the @@ -413,6 +475,7 @@ class IRenderer(Interface): view), and ``request`` (the request object passed to the view).""" + class ITemplateRenderer(IRenderer): def implementation(): """ Return the object that the underlying templating system @@ -420,12 +483,14 @@ class ITemplateRenderer(IRenderer): accepts arbitrary keyword arguments and returns a string or unicode object """ + deprecated( 'ITemplateRenderer', 'As of Pyramid 1.5 the, "pyramid.interfaces.ITemplateRenderer" interface ' 'is scheduled to be removed. It was used by the Mako and Chameleon ' - 'renderers which have been split into their own packages.' - ) + 'renderers which have been split into their own packages.', +) + class IViewMapper(Interface): def __call__(self, object): @@ -435,6 +500,7 @@ class IViewMapper(Interface): object. An IViewMapper is returned by :class:`pyramid.interfaces.IViewMapperFactory`.""" + class IViewMapperFactory(Interface): def __call__(self, **kw): """ @@ -448,6 +514,7 @@ class IViewMapperFactory(Interface): invocation signatures and response values. """ + class IAuthenticationPolicy(Interface): """ An object representing a Pyramid authentication policy. """ @@ -500,8 +567,10 @@ class IAuthenticationPolicy(Interface): """ + class IAuthorizationPolicy(Interface): """ An object representing a Pyramid authorization policy. """ + def permits(context, principals, permission): """ Return an instance of :class:`pyramid.security.Allowed` if any of the ``principals`` is allowed the ``permission`` in the current @@ -518,7 +587,8 @@ class IAuthorizationPolicy(Interface): ``pyramid.security.principals_allowed_by_permission`` API is used.""" -class IMultiDict(IDict): # docs-only interface + +class IMultiDict(IDict): # docs-only interface """ An ordered dictionary that can have multiple values for each key. A multidict adds the methods ``getall``, ``getone``, ``mixed``, ``extend``, @@ -556,36 +626,46 @@ class IMultiDict(IDict): # docs-only interface dictionary. This is similar to the kind of dictionary often used to represent the variables in a web request. """ + # internal interfaces + class IRequest(Interface): """ Request type interface attached to all request objects """ + class ITweens(Interface): """ Marker interface for utility registration representing the ordered set of a configuration's tween factories""" + class IRequestHandler(Interface): """ """ + def __call__(self, request): """ Must return a tuple of IReqest, IResponse or raise an exception. The ``request`` argument will be an instance of an object that provides IRequest.""" -IRequest.combined = IRequest # for exception view lookups + +IRequest.combined = IRequest # for exception view lookups + class IRequestExtensions(Interface): """ Marker interface for storing request extensions (properties and methods) which will be added to the request object.""" + descriptors = Attribute( - """A list of descriptors that will be added to each request.""") - methods = Attribute( - """A list of methods to be added to each request.""") + """A list of descriptors that will be added to each request.""" + ) + methods = Attribute("""A list of methods to be added to each request.""") + class IRouteRequest(Interface): """ *internal only* interface used as in a utility lookup to find route-specific interfaces. Not an API.""" + class IAcceptOrder(Interface): """ Marker interface for a list of accept headers with the most important @@ -593,8 +673,10 @@ class IAcceptOrder(Interface): """ + class IStaticURLInfo(Interface): """ A policy for generating URLs to static assets """ + def add(config, name, spec, **extra): """ Add a new static info registration """ @@ -604,15 +686,19 @@ class IStaticURLInfo(Interface): def add_cache_buster(config, spec, cache_buster): """ Add a new cache buster to a particular set of assets """ + class IResponseFactory(Interface): """ A utility which generates a response """ + def __call__(request): """ Return a response object implementing IResponse, e.g. :class:`pyramid.response.Response`). It should handle the case when ``request`` is ``None``.""" + class IRequestFactory(Interface): """ A utility which generates a request """ + def __call__(environ): """ Return an instance of ``pyramid.request.Request``""" @@ -620,18 +706,23 @@ class IRequestFactory(Interface): """ Return an empty request object (see :meth:`pyramid.request.Request.blank`)""" + class IViewClassifier(Interface): """ *Internal only* marker interface for views.""" + class IExceptionViewClassifier(Interface): """ *Internal only* marker interface for exception views.""" + class IView(Interface): def __call__(context, request): """ Must return an object that implements IResponse. """ + class ISecuredView(IView): """ *Internal only* interface. Not an API. """ + def __call_permissive__(context, request): """ Guaranteed-permissive version of __call__ """ @@ -639,21 +730,26 @@ class ISecuredView(IView): """ Return True if view execution will be permitted using the context and request, False otherwise""" + class IMultiView(ISecuredView): """ *internal only*. A multiview is a secured view that is a collection of other views. Each of the views is associated with zero or more predicates. Not an API.""" + def add(view, predicates, order, accept=None, phash=None): """ Add a view to the multiview. """ + class IRootFactory(Interface): def __call__(request): """ Return a root object based on the request """ + class IDefaultRootFactory(Interface): def __call__(request): """ Return the *default* root object for an application """ + class ITraverser(Interface): def __call__(request): """ Return a dictionary with (at least) the keys ``root``, @@ -678,21 +774,26 @@ class ITraverser(Interface): as attributes of the ``request`` object by the :term:`router`. """ -ITraverserFactory = ITraverser # b / c for 1.0 code + +ITraverserFactory = ITraverser # b / c for 1.0 code + class IViewPermission(Interface): def __call__(context, request): """ Return True if the permission allows, return False if it denies. """ + class IRouter(Interface): """ WSGI application which routes requests to 'view' code based on a view registry. """ + registry = Attribute( - """Component architecture registry local to this application.""") + """Component architecture registry local to this application.""" + ) def request_context(environ): """ @@ -734,6 +835,7 @@ class IRouter(Interface): """ + class IExecutionPolicy(Interface): def __call__(environ, router): """ @@ -762,22 +864,28 @@ class IExecutionPolicy(Interface): return request.invoke_exception_view(reraise=True) """ + class ISettings(IDict): """ Runtime settings utility for pyramid; represents the deployment settings for the application. Implements a mapping interface.""" + # this interface, even if it becomes unused within Pyramid, is # imported by other packages (such as traversalwrapper) class ILocation(Interface): """Objects that have a structural location""" + __parent__ = Attribute("The parent in the location hierarchy") __name__ = Attribute("The name within the parent") + class IDebugLogger(Interface): """ Interface representing a PEP 282 logger """ -ILogger = IDebugLogger # b/c + +ILogger = IDebugLogger # b/c + class IRoutePregenerator(Interface): def __call__(request, elements, kw): @@ -804,21 +912,27 @@ class IRoutePregenerator(Interface): """ + class IRoute(Interface): """ Interface representing the type of object returned from ``IRoutesMapper.get_route``""" + name = Attribute('The route name') pattern = Attribute('The route pattern') factory = Attribute( 'The :term:`root factory` used by the :app:`Pyramid` router ' - 'when this route matches (or ``None``)') + 'when this route matches (or ``None``)' + ) predicates = Attribute( 'A sequence of :term:`route predicate` objects used to ' 'determine if a request matches this route or not after ' - 'basic pattern matching has been completed.') - pregenerator = Attribute('This attribute should either be ``None`` or ' - 'a callable object implementing the ' - '``IRoutePregenerator`` interface') + 'basic pattern matching has been completed.' + ) + pregenerator = Attribute( + 'This attribute should either be ``None`` or ' + 'a callable object implementing the ' + '``IRoutePregenerator`` interface' + ) def match(path): """ @@ -831,14 +945,17 @@ class IRoute(Interface): If the ``path`` passed to this function cannot be matched by the ``pattern`` of this route, return ``None``. """ + def generate(kw): """ Generate a URL based on filling in the dynamic segment markers in the pattern using the ``kw`` dictionary provided. """ + class IRoutesMapper(Interface): """ Interface representing a Routes ``Mapper`` object """ + def get_routes(): """ Return a sequence of Route objects registered in the mapper. Static routes will not be returned in this sequence.""" @@ -850,8 +967,14 @@ class IRoutesMapper(Interface): """ Returns an ``IRoute`` object if a route with the name ``name`` was registered, otherwise return ``None``.""" - def connect(name, pattern, factory=None, predicates=(), pregenerator=None, - static=True): + def connect( + name, + pattern, + factory=None, + predicates=(), + pregenerator=None, + static=True, + ): """ Add a new route. """ def generate(name, kw): @@ -865,23 +988,26 @@ class IRoutesMapper(Interface): ``match`` key will be the matchdict or ``None`` if no route matched. Static routes will not be considered for matching. """ + class IResourceURL(Interface): virtual_path = Attribute( 'The virtual url path of the resource as a string.' - ) + ) physical_path = Attribute( 'The physical url path of the resource as a string.' - ) + ) virtual_path_tuple = Attribute( 'The virtual url path of the resource as a tuple. (New in 1.5)' - ) + ) physical_path_tuple = Attribute( 'The physical url path of the resource as a tuple. (New in 1.5)' - ) + ) + class IPEP302Loader(Interface): """ See http://www.python.org/dev/peps/pep-0302/#id30. """ + def get_data(path): """ Retrieve data for and arbitrary "files" from storage backend. @@ -924,43 +1050,54 @@ class IPEP302Loader(Interface): class IPackageOverrides(IPEP302Loader): """ Utility for pkg_resources overrides """ + # VH_ROOT_KEY is an interface; its imported from other packages (e.g. # traversalwrapper) VH_ROOT_KEY = 'HTTP_X_VHM_ROOT' + class ILocalizer(Interface): """ Localizer for a specific language """ + class ILocaleNegotiator(Interface): def __call__(request): """ Return a locale name """ + class ITranslationDirectories(Interface): """ A list object representing all known translation directories for an application""" + class IDefaultPermission(Interface): """ A string object representing the default permission to be used for all view configurations which do not explicitly declare their own.""" + class IDefaultCSRFOptions(Interface): """ An object representing the default CSRF settings to be used for all view configurations which do not explicitly declare their own.""" + require_csrf = Attribute( 'Boolean attribute. If ``True``, then CSRF checks will be enabled by ' - 'default for the view unless overridden.') + 'default for the view unless overridden.' + ) token = Attribute('The key to be matched in the body of the request.') header = Attribute('The header to be matched with the CSRF token.') safe_methods = Attribute('A set of safe methods that skip CSRF checks.') callback = Attribute('A callback to disable CSRF checks per-request.') + class ISessionFactory(Interface): """ An interface representing a factory which accepts a request object and returns an ISession object """ + def __call__(request): """ Return an ISession object """ + class ISession(IDict): """ An interface representing a session (a web session object, usually accessed via ``request.session``. @@ -1158,16 +1295,21 @@ class IIntrospectable(Interface): title = Attribute('Text title describing this introspectable') type_name = Attribute('Text type name describing this introspectable') - order = Attribute('integer order in which registered with introspector ' - '(managed by introspector, usually)') + order = Attribute( + 'integer order in which registered with introspector ' + '(managed by introspector, usually)' + ) category_name = Attribute('introspection category name') - discriminator = Attribute('introspectable discriminator (within category) ' - '(must be hashable)') + discriminator = Attribute( + 'introspectable discriminator (within category) ' '(must be hashable)' + ) discriminator_hash = Attribute('an integer hash of the discriminator') - action_info = Attribute('An IActionInfo object representing the caller ' - 'that invoked the creation of this introspectable ' - '(usually a sentinel until updated during ' - 'self.register)') + action_info = Attribute( + 'An IActionInfo object representing the caller ' + 'that invoked the creation of this introspectable ' + '(usually a sentinel until updated during ' + 'self.register)' + ) def relate(category_name, discriminator): """ Indicate an intent to relate this IIntrospectable with another @@ -1209,19 +1351,22 @@ class IIntrospectable(Interface): return hash((self.category_name,) + (self.discriminator,)) """ + class IActionInfo(Interface): """ Class which provides code introspection capability associated with an action. The ParserInfo class used by ZCML implements the same interface.""" - file = Attribute( - 'Filename of action-invoking code as a string') + + file = Attribute('Filename of action-invoking code as a string') line = Attribute( 'Starting line number in file (as an integer) of action-invoking code.' - 'This will be ``None`` if the value could not be determined.') + 'This will be ``None`` if the value could not be determined.' + ) def __str__(): """ Return a representation of the action information (including source code from file, if possible) """ + class IAssetDescriptor(Interface): """ Describes an :term:`asset`. @@ -1260,19 +1405,24 @@ class IAssetDescriptor(Interface): Returns True if asset exists, otherwise returns False. """ + class IJSONAdapter(Interface): """ Marker interface for objects that can convert an arbitrary object into a JSON-serializable primitive. """ + class IPredicateList(Interface): """ Interface representing a predicate list """ + class IViewDeriver(Interface): - options = Attribute('A list of supported options to be passed to ' - ':meth:`pyramid.config.Configurator.add_view`. ' - 'This attribute is optional.') + options = Attribute( + 'A list of supported options to be passed to ' + ':meth:`pyramid.config.Configurator.add_view`. ' + 'This attribute is optional.' + ) def __call__(view, info): """ @@ -1285,24 +1435,35 @@ class IViewDeriver(Interface): """ + class IViewDeriverInfo(Interface): """ An object implementing this interface is passed to every :term:`view deriver` during configuration.""" - registry = Attribute('The "current" application registry where the ' - 'view was created') - package = Attribute('The "current package" where the view ' - 'configuration statement was found') - settings = Attribute('The deployment settings dictionary related ' - 'to the current application') - options = Attribute('The view options passed to the view, including any ' - 'default values that were not overriden') + + registry = Attribute( + 'The "current" application registry where the ' 'view was created' + ) + package = Attribute( + 'The "current package" where the view ' + 'configuration statement was found' + ) + settings = Attribute( + 'The deployment settings dictionary related ' + 'to the current application' + ) + options = Attribute( + 'The view options passed to the view, including any ' + 'default values that were not overriden' + ) predicates = Attribute('The list of predicates active on the view') original_view = Attribute('The original view object being wrapped') exception_only = Attribute('The view will only be invoked for exceptions') + class IViewDerivers(Interface): """ Interface for view derivers list """ + class ICacheBuster(Interface): """ A cache buster modifies the URL generation machinery for @@ -1310,6 +1471,7 @@ class ICacheBuster(Interface): .. versionadded:: 1.6 """ + def __call__(request, subpath, kw): """ Modifies a subpath and/or keyword arguments from which a static asset @@ -1344,6 +1506,7 @@ class ICacheBuster(Interface): ``config.override_asset('myapp:static/foo.png', 'themepkg:bar.png')``. """ + # configuration phases: a lower phase number means the actions associated # with this phase will be executed earlier than those with later phase # numbers. The default phase number is 0, FTR. diff --git a/src/pyramid/location.py b/src/pyramid/location.py index 4124895a5..b8542d1b9 100644 --- a/src/pyramid/location.py +++ b/src/pyramid/location.py @@ -12,6 +12,7 @@ # ############################################################################## + def inside(resource1, resource2): """Is ``resource1`` 'inside' ``resource2``? Return ``True`` if so, else ``False``. @@ -28,6 +29,7 @@ def inside(resource1, resource2): return False + def lineage(resource): """ Return a generator representing the :term:`lineage` of the @@ -63,4 +65,3 @@ def lineage(resource): resource = resource.__parent__ except AttributeError: resource = None - diff --git a/src/pyramid/paster.py b/src/pyramid/paster.py index f7544f0c5..eda479476 100644 --- a/src/pyramid/paster.py +++ b/src/pyramid/paster.py @@ -1,6 +1,7 @@ from pyramid.scripting import prepare from pyramid.scripts.common import get_config_loader + def setup_logging(config_uri, global_conf=None): """ Set up Python logging with the filename specified via ``config_uri`` @@ -11,6 +12,7 @@ def setup_logging(config_uri, global_conf=None): loader = get_config_loader(config_uri) loader.setup_logging(global_conf) + def get_app(config_uri, name=None, options=None): """ Return the WSGI application named ``name`` in the PasteDeploy config file specified by ``config_uri``. @@ -27,6 +29,7 @@ def get_app(config_uri, name=None, options=None): loader = get_config_loader(config_uri) return loader.get_wsgi_app(name, options) + def get_appsettings(config_uri, name=None, options=None): """ Return a dictionary representing the key/value pairs in an ``app`` section within the file represented by ``config_uri``. @@ -43,6 +46,7 @@ def get_appsettings(config_uri, name=None, options=None): loader = get_config_loader(config_uri) return loader.get_wsgi_app_settings(name, options) + def bootstrap(config_uri, request=None, options=None): """ Load a WSGI application from the PasteDeploy config file specified by ``config_uri``. The environment will be configured as if it is @@ -108,4 +112,3 @@ def bootstrap(config_uri, request=None, options=None): env = prepare(request) env['app'] = app return env - diff --git a/src/pyramid/path.py b/src/pyramid/path.py index 3fac7e940..c70be99db 100644 --- a/src/pyramid/path.py +++ b/src/pyramid/path.py @@ -9,9 +9,13 @@ 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] for x in imp.get_suffixes() if - x[0] and x[2] not in ignore_types ] +ignore_types = [imp.C_EXTENSION, imp.C_BUILTIN] +init_names = [ + '__init__%s' % x[0] + for x in imp.get_suffixes() + if x[0] and x[2] not in ignore_types +] + def caller_path(path, level=2): if not os.path.isabs(path): @@ -20,12 +24,14 @@ def caller_path(path, level=2): path = os.path.join(prefix, path) return path + def caller_module(level=2, sys=sys): module_globals = sys._getframe(level).f_globals module_name = module_globals.get('__name__') or '__main__' module = sys.modules[module_name] return module + def package_name(pkg_or_module): """ If this function is passed a module, return the dotted Python package name of the package in which the module lives. If this @@ -45,23 +51,26 @@ def package_name(pkg_or_module): return pkg_name return pkg_name.rsplit('.', 1)[0] + def package_of(pkg_or_module): """ Return the package of a module or return the package itself """ pkg_name = package_name(pkg_or_module) __import__(pkg_name) return sys.modules[pkg_name] + def caller_package(level=2, caller_module=caller_module): # caller_module in arglist for tests module = caller_module(level + 1) f = getattr(module, '__file__', '') - if (('__init__.py' in f) or ('__init__$py' in f)): # empty at >>> + if ('__init__.py' in f) or ('__init__$py' in f): # empty at >>> # Module is a package return module # Go up one level to get package package_name = module.__name__.rsplit('.', 1)[0] return sys.modules[package_name] + def package_path(package): # computing the abspath is actually kinda expensive so we memoize # the result @@ -78,12 +87,15 @@ def package_path(package): pass return prefix + class _CALLER_PACKAGE(object): - def __repr__(self): # pragma: no cover (for docs) + def __repr__(self): # pragma: no cover (for docs) return 'pyramid.path.CALLER_PACKAGE' + CALLER_PACKAGE = _CALLER_PACKAGE() + class Resolver(object): def __init__(self, package=CALLER_PACKAGE): if package in (None, CALLER_PACKAGE): @@ -95,7 +107,7 @@ class Resolver(object): except ImportError: raise ValueError( 'The dotted name %r cannot be imported' % (package,) - ) + ) package = sys.modules[package] self.package = package_of(package) @@ -164,6 +176,7 @@ class AssetResolver(Resolver): to the :meth:`~pyramid.path.AssetResolver.resolve` method, the resulting absolute asset spec would be ``xml.minidom:template.pt``. """ + def resolve(self, spec): """ Resolve the asset spec named as ``spec`` to an object that has the @@ -208,6 +221,7 @@ class AssetResolver(Resolver): ) return PkgResourcesAssetDescriptor(package_name, path) + class DottedNameResolver(Resolver): """ A class used to resolve a :term:`dotted Python name` to a package or module object. @@ -258,6 +272,7 @@ class DottedNameResolver(Resolver): :meth:`~pyramid.path.DottedNameResolver.resolve` method, the resulting import would be for ``xml.minidom``. """ + def resolve(self, dotted): """ This method resolves a dotted name reference to a global Python @@ -332,7 +347,7 @@ class DottedNameResolver(Resolver): if not package: raise ValueError( 'relative name %r irresolveable without package' % (value,) - ) + ) if value in ['.', ':']: value = package.__name__ else: @@ -348,7 +363,7 @@ class DottedNameResolver(Resolver): def _zope_dottedname_style(self, value, package): """ package.module.attr style """ - module = getattr(package, '__name__', None) # package may be None + module = getattr(package, '__name__', None) # package may be None if not module: module = None if value == '.': @@ -364,7 +379,7 @@ class DottedNameResolver(Resolver): raise ValueError( 'relative name %r irresolveable without ' 'package' % (value,) - ) + ) module = module.split('.') name.pop(0) while not name[0]: @@ -380,10 +395,11 @@ class DottedNameResolver(Resolver): found = getattr(found, n) except AttributeError: __import__(used) - found = getattr(found, n) # pragma: no cover + found = getattr(found, n) # pragma: no cover return found + @implementer(IAssetDescriptor) class PkgResourcesAssetDescriptor(object): pkg_resources = pkg_resources @@ -397,7 +413,8 @@ class PkgResourcesAssetDescriptor(object): def abspath(self): return os.path.abspath( - self.pkg_resources.resource_filename(self.pkg_name, self.path)) + self.pkg_resources.resource_filename(self.pkg_name, self.path) + ) def stream(self): return self.pkg_resources.resource_stream(self.pkg_name, self.path) @@ -411,9 +428,9 @@ class PkgResourcesAssetDescriptor(object): def exists(self): return self.pkg_resources.resource_exists(self.pkg_name, self.path) + @implementer(IAssetDescriptor) class FSAssetDescriptor(object): - def __init__(self, path): self.path = os.path.abspath(path) diff --git a/src/pyramid/predicates.py b/src/pyramid/predicates.py index 97edae8a0..b95dfd9be 100644 --- a/src/pyramid/predicates.py +++ b/src/pyramid/predicates.py @@ -8,17 +8,15 @@ from pyramid.csrf import check_csrf_token from pyramid.traversal import ( find_interface, traversal_path, - resource_path_tuple - ) + resource_path_tuple, +) from pyramid.urldispatch import _compile_route -from pyramid.util import ( - as_sorted_tuple, - object_description, -) +from pyramid.util import as_sorted_tuple, object_description _marker = object() + class XHRPredicate(object): def __init__(self, val, config): self.val = bool(val) @@ -31,6 +29,7 @@ class XHRPredicate(object): def __call__(self, context, request): return bool(request.is_xhr) is self.val + class RequestMethodPredicate(object): def __init__(self, val, config): request_method = as_sorted_tuple(val) @@ -47,6 +46,7 @@ class RequestMethodPredicate(object): def __call__(self, context, request): return request.method in self.val + class PathInfoPredicate(object): def __init__(self, val, config): self.orig = val @@ -63,7 +63,8 @@ class PathInfoPredicate(object): def __call__(self, context, request): return self.val.match(request.upath_info) is not None - + + class RequestParamPredicate(object): def __init__(self, val, config): val = as_sorted_tuple(val) @@ -85,7 +86,7 @@ class RequestParamPredicate(object): def text(self): return 'request_param %s' % ','.join( - ['%s=%s' % (x,y) if y else x for x, y in self.reqs] + ['%s=%s' % (x, y) if y else x for x, y in self.reqs] ) phash = text @@ -99,6 +100,7 @@ class RequestParamPredicate(object): return False return True + class HeaderPredicate(object): def __init__(self, val, config): name = val @@ -129,6 +131,7 @@ class HeaderPredicate(object): return False return self.val.match(val) is not None + class AcceptPredicate(object): _is_using_deprecated_ranges = False @@ -151,6 +154,7 @@ class AcceptPredicate(object): return self.values[0] in request.accept return bool(request.accept.acceptable_offers(self.values)) + class ContainmentPredicate(object): def __init__(self, val, config): self.val = config.maybe_dotted(val) @@ -163,7 +167,8 @@ class ContainmentPredicate(object): def __call__(self, context, request): ctx = getattr(request, 'context', context) return find_interface(ctx, self.val) is not None - + + class RequestTypePredicate(object): def __init__(self, val, config): self.val = val @@ -175,18 +180,19 @@ class RequestTypePredicate(object): def __call__(self, context, request): return self.val.providedBy(request) - + + class MatchParamPredicate(object): def __init__(self, val, config): val = as_sorted_tuple(val) self.val = val - reqs = [ p.split('=', 1) for p in val ] - self.reqs = [ (x.strip(), y.strip()) for x, y in reqs ] + reqs = [p.split('=', 1) for p in val] + self.reqs = [(x.strip(), y.strip()) for x, y in reqs] def text(self): return 'match_param %s' % ','.join( - ['%s=%s' % (x,y) for x, y in self.reqs] - ) + ['%s=%s' % (x, y) for x, y in self.reqs] + ) phash = text @@ -198,7 +204,8 @@ class MatchParamPredicate(object): if request.matchdict.get(k) != v: return False return True - + + class CustomPredicate(object): def __init__(self, func, config): self.func = func @@ -207,8 +214,8 @@ class CustomPredicate(object): return getattr( self.func, '__text__', - 'custom predicate: %s' % object_description(self.func) - ) + 'custom predicate: %s' % object_description(self.func), + ) def phash(self): # using hash() here rather than id() is intentional: we @@ -221,8 +228,8 @@ class CustomPredicate(object): def __call__(self, context, request): return self.func(context, request) - - + + class TraversePredicate(object): # Can only be used as a *route* "predicate"; it adds 'traverse' to the # matchdict if it's specified in the routing args. This causes the @@ -231,7 +238,7 @@ class TraversePredicate(object): def __init__(self, val, config): _, self.tgenerate = _compile_route(val) self.val = val - + def text(self): return 'traverse matchdict pseudo-predicate' @@ -252,10 +259,11 @@ class TraversePredicate(object): # return True. return True + class CheckCSRFTokenPredicate(object): - check_csrf_token = staticmethod(check_csrf_token) # testing - + check_csrf_token = staticmethod(check_csrf_token) # testing + def __init__(self, val, config): self.val = val @@ -272,6 +280,7 @@ class CheckCSRFTokenPredicate(object): return self.check_csrf_token(request, val, raises=False) return True + class PhysicalPathPredicate(object): def __init__(self, val, config): if is_nonstr_iter(val): @@ -290,6 +299,7 @@ class PhysicalPathPredicate(object): return resource_path_tuple(context) == self.val return False + class EffectivePrincipalsPredicate(object): def __init__(self, val, config): if is_nonstr_iter(val): @@ -310,6 +320,7 @@ class EffectivePrincipalsPredicate(object): return True return False + class Notted(object): def __init__(self, predicate): self.predicate = predicate diff --git a/src/pyramid/registry.py b/src/pyramid/registry.py index a741c495e..c24125830 100644 --- a/src/pyramid/registry.py +++ b/src/pyramid/registry.py @@ -7,19 +7,13 @@ 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.interfaces import IIntrospector, IIntrospectable, ISettings -from pyramid.path import ( - CALLER_PACKAGE, - caller_package, -) +from pyramid.path import CALLER_PACKAGE, caller_package empty = text_('') + class Registry(Components, dict): """ A registry object is an :term:`application registry`. @@ -82,13 +76,19 @@ class Registry(Components, dict): self.has_listeners = True return result - def registerSelfAdapter(self, required=None, provided=None, name=empty, - info=empty, event=True): + def registerSelfAdapter( + self, required=None, provided=None, name=empty, info=empty, event=True + ): # registerAdapter analogue which always returns the object itself # when required is matched - return self.registerAdapter(lambda x: x, required=required, - provided=provided, name=name, - info=info, event=event) + return self.registerAdapter( + lambda x: x, + required=required, + provided=provided, + name=name, + info=info, + event=event, + ) def queryAdapterOrSelf(self, object, interface, default=None): # queryAdapter analogue which returns the object if it implements @@ -106,7 +106,7 @@ class Registry(Components, dict): def notify(self, *events): if self.has_listeners: # iterating over subscribers assures they get executed - [ _ for _ in self.subscribers(events, None) ] + [_ for _ in self.subscribers(events, None)] # backwards compatibility for code that wants to look up a settings # object via ``registry.getUtility(ISettings)`` @@ -119,6 +119,7 @@ class Registry(Components, dict): settings = property(_get_settings, _set_settings) + @implementer(IIntrospector) class Introspector(object): def __init__(self): @@ -147,16 +148,19 @@ class Introspector(object): values = category.values() values = sorted(set(values), key=sort_key) return [ - {'introspectable': intr, - 'related': self.related(intr)} + {'introspectable': intr, 'related': self.related(intr)} for intr in values ] def categorized(self, sort_key=None): L = [] for category_name in self.categories(): - L.append((category_name, self.get_category(category_name, - sort_key=sort_key))) + L.append( + ( + category_name, + self.get_category(category_name, sort_key=sort_key), + ) + ) return L def categories(self): @@ -186,7 +190,7 @@ class Introspector(object): def relate(self, *pairs): introspectables = self._get_intrs_by_pairs(pairs) - relatable = ((x,y) for x in introspectables for y in introspectables) + relatable = ((x, y) for x in introspectables for y in introspectables) for x, y in relatable: L = self._refs.setdefault(x, []) if x is not y and y not in L: @@ -194,7 +198,7 @@ class Introspector(object): def unrelate(self, *pairs): introspectables = self._get_intrs_by_pairs(pairs) - relatable = ((x,y) for x in introspectables for y in introspectables) + relatable = ((x, y) for x in introspectables for y in introspectables) for x, y in relatable: L = self._refs.get(x, []) if y in L: @@ -207,11 +211,12 @@ class Introspector(object): raise KeyError((category_name, discriminator)) return self._refs.get(intr, []) + @implementer(IIntrospectable) class Introspectable(dict): - order = 0 # mutated by introspector.add - action_info = None # mutated by self.register + order = 0 # mutated by introspector.add + action_info = None # mutated by self.register def __init__(self, category_name, discriminator, title, type_name): self.category_name = category_name @@ -240,14 +245,16 @@ class Introspectable(dict): def __repr__(self): self._assert_resolved() - return '<%s category %r, discriminator %r>' % (self.__class__.__name__, - self.category_name, - self.discriminator) + return '<%s category %r, discriminator %r>' % ( + self.__class__.__name__, + self.category_name, + self.discriminator, + ) def __nonzero__(self): return True - __bool__ = __nonzero__ # py3 + __bool__ = __nonzero__ # py3 def register(self, introspector, action_info): self.discriminator = undefer(self.discriminator) @@ -261,8 +268,9 @@ class Introspectable(dict): method = introspector.unrelate method( (self.category_name, self.discriminator), - (category_name, discriminator) - ) + (category_name, discriminator), + ) + class Deferred(object): """ Can be used by a third-party configuration extender to wrap a @@ -270,6 +278,7 @@ class Deferred(object): discriminator cannot be computed because it relies on unresolved values. The function should accept no arguments and should return a hashable discriminator.""" + def __init__(self, func): self.func = func @@ -282,6 +291,7 @@ class Deferred(object): def resolve(self): return self.value + def undefer(v): """ Function which accepts an object and returns it unless it is a :class:`pyramid.registry.Deferred` instance. If it is an instance of @@ -291,7 +301,9 @@ def undefer(v): v = v.resolve() return v + class predvalseq(tuple): """ A subtype of tuple used to represent a sequence of predicate values """ + global_registry = Registry('global') diff --git a/src/pyramid/renderers.py b/src/pyramid/renderers.py index d1c85b371..a8e3ec16f 100644 --- a/src/pyramid/renderers.py +++ b/src/pyramid/renderers.py @@ -3,22 +3,12 @@ import json import os import re -from zope.interface import ( - implementer, - providedBy, - ) +from zope.interface import implementer, providedBy from zope.interface.registry import Components -from pyramid.interfaces import ( - IJSONAdapter, - IRendererFactory, - IRendererInfo, - ) +from pyramid.interfaces import IJSONAdapter, IRendererFactory, IRendererInfo -from pyramid.compat import ( - string_types, - text_type, - ) +from pyramid.compat import string_types, text_type from pyramid.csrf import get_csrf_token from pyramid.decorator import reify @@ -35,6 +25,7 @@ from pyramid.util import hide_attrs # API + def render(renderer_name, value, request=None, package=None): """ Using the renderer ``renderer_name`` (a template or a static renderer), render the value (or set of values) present @@ -76,19 +67,19 @@ def render(renderer_name, value, request=None, package=None): registry = None if package is None: package = caller_package() - helper = RendererHelper(name=renderer_name, package=package, - registry=registry) + helper = RendererHelper( + name=renderer_name, package=package, registry=registry + ) with hide_attrs(request, 'response'): result = helper.render(value, None, request=request) return result -def render_to_response(renderer_name, - value, - request=None, - package=None, - response=None): + +def render_to_response( + renderer_name, value, request=None, package=None, response=None +): """ Using the renderer ``renderer_name`` (a template or a static renderer), render the value (or set of values) using the result of the renderer's ``__call__`` method (usually a string @@ -137,8 +128,9 @@ def render_to_response(renderer_name, registry = None if package is None: package = caller_package() - helper = RendererHelper(name=renderer_name, package=package, - registry=registry) + helper = RendererHelper( + name=renderer_name, package=package, registry=registry + ) with hide_attrs(request, 'response'): if response is not None: @@ -147,6 +139,7 @@ def render_to_response(renderer_name, return result + def get_renderer(renderer_name, package=None, registry=None): """ Return the renderer object for the renderer ``renderer_name``. @@ -165,12 +158,15 @@ def get_renderer(renderer_name, package=None, registry=None): """ if package is None: package = caller_package() - helper = RendererHelper(name=renderer_name, package=package, - registry=registry) + helper = RendererHelper( + name=renderer_name, package=package, registry=registry + ) return helper.renderer + # concrete renderer factory implementations (also API) + def string_renderer_factory(info): def _render(value, system): if not isinstance(value, string_types): @@ -182,10 +178,13 @@ def string_renderer_factory(info): if ct == response.default_content_type: response.content_type = 'text/plain' return value + return _render + _marker = object() + class JSON(object): """ Renderer that returns a JSON-encoded string. @@ -265,13 +264,15 @@ class JSON(object): instances of the ``Foo`` class when they're encountered in your view results.""" - self.components.registerAdapter(adapter, (type_or_iface,), - IJSONAdapter) + self.components.registerAdapter( + adapter, (type_or_iface,), IJSONAdapter + ) def __call__(self, info): """ Returns a plain JSON-encoded string with content-type ``application/json``. The content-type may be overridden by setting ``request.response.content_type``.""" + def _render(value, system): request = system.get('request') if request is not None: @@ -290,17 +291,21 @@ class JSON(object): return obj.__json__(request) obj_iface = providedBy(obj) adapters = self.components.adapters - result = adapters.lookup((obj_iface,), IJSONAdapter, - default=_marker) + result = adapters.lookup( + (obj_iface,), IJSONAdapter, default=_marker + ) if result is _marker: raise TypeError('%r is not JSON serializable' % (obj,)) return result(obj, request) + return default -json_renderer_factory = JSON() # bw compat + +json_renderer_factory = JSON() # bw compat JSONP_VALID_CALLBACK = re.compile(r"^[$a-z_][$0-9a-z_\.\[\]]+[^.]$", re.I) + class JSONP(JSON): """ `JSONP <https://en.wikipedia.org/wiki/JSONP>`_ renderer factory helper which implements a hybrid json/jsonp renderer. JSONP is useful for @@ -373,6 +378,7 @@ class JSONP(JSON): ``application/javascript`` if query parameter matching ``self.param_name`` is present in request.GET; otherwise returns plain-JSON encoded string with content-type ``application/json``""" + def _render(value, system): request = system.get('request') default = self._make_default(request) @@ -384,7 +390,9 @@ class JSONP(JSON): if callback is not None: if not JSONP_VALID_CALLBACK.match(callback): - raise HTTPBadRequest('Invalid JSONP callback function name.') + raise HTTPBadRequest( + 'Invalid JSONP callback function name.' + ) ct = 'application/javascript' body = '/**/{0}({1});'.format(callback, val) @@ -392,8 +400,10 @@ class JSONP(JSON): if response.content_type == response.default_content_type: response.content_type = ct return body + return _render + @implementer(IRendererInfo) class RendererHelper(object): def __init__(self, name=None, package=None, registry=None): @@ -422,36 +432,36 @@ class RendererHelper(object): def renderer(self): factory = self.registry.queryUtility(IRendererFactory, name=self.type) if factory is None: - raise ValueError( - 'No such renderer factory %s' % str(self.type)) + raise ValueError('No such renderer factory %s' % str(self.type)) return factory(self) def get_renderer(self): return self.renderer def render_view(self, request, response, view, context): - system = {'view':view, - 'renderer_name':self.name, # b/c - 'renderer_info':self, - 'context':context, - 'request':request, - 'req':request, - 'get_csrf_token':partial(get_csrf_token, request), - } + system = { + 'view': view, + 'renderer_name': self.name, # b/c + 'renderer_info': self, + 'context': context, + 'request': request, + 'req': request, + 'get_csrf_token': partial(get_csrf_token, request), + } return self.render_to_response(response, system, request=request) def render(self, value, system_values, request=None): renderer = self.renderer if system_values is None: system_values = { - 'view':None, - 'renderer_name':self.name, # b/c - 'renderer_info':self, - 'context':getattr(request, 'context', None), - 'request':request, - 'req':request, - 'get_csrf_token':partial(get_csrf_token, request), - } + 'view': None, + 'renderer_name': self.name, # b/c + 'renderer_info': self, + 'context': getattr(request, 'context', None), + 'request': request, + 'req': request, + 'get_csrf_token': partial(get_csrf_token, request), + } system_values = BeforeRender(system_values, value) @@ -495,12 +505,14 @@ class RendererHelper(object): registry = self.registry return self.__class__(name=name, package=package, registry=registry) + class NullRendererHelper(RendererHelper): """ Special renderer helper that has render_* methods which simply return the value they are fed rather than converting them to response objects; useful for testing purposes and special case view configuration registrations that want to use the view configuration machinery but do not want actual rendering to happen .""" + def __init__(self, name=None, package=None, registry=None): # we override the initializer to avoid calling get_current_registry # (it will return a reference to the global registry when this @@ -526,4 +538,5 @@ class NullRendererHelper(RendererHelper): def clone(self, name=None, package=None, registry=None): return self + null_renderer = NullRendererHelper() diff --git a/src/pyramid/request.py b/src/pyramid/request.py index 201f1d648..907b4477f 100644 --- a/src/pyramid/request.py +++ b/src/pyramid/request.py @@ -11,32 +11,23 @@ from pyramid.interfaces import ( IRequestExtensions, IResponse, ISessionFactory, - ) +) -from pyramid.compat import ( - text_, - bytes_, - native_, - iteritems_, - ) +from pyramid.compat import text_, bytes_, native_, iteritems_ 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.security import AuthenticationAPIMixin, AuthorizationAPIMixin from pyramid.url import URLMethodsMixin -from pyramid.util import ( - InstancePropertyHelper, - InstancePropertyMixin, -) +from pyramid.util import InstancePropertyHelper, InstancePropertyMixin from pyramid.view import ViewMethodsMixin + class TemplateContext(object): pass + class CallbackMethodsMixin(object): @reify def finished_callbacks(self): @@ -146,6 +137,7 @@ class CallbackMethodsMixin(object): callback = callbacks.popleft() callback(self) + @implementer(IRequest) class Request( BaseRequest, @@ -156,7 +148,7 @@ class Request( AuthenticationAPIMixin, AuthorizationAPIMixin, ViewMethodsMixin, - ): +): """ A subclass of the :term:`WebOb` Request class. An instance of this class is created by the :term:`router` and is provided to a @@ -177,6 +169,7 @@ class Request( release of this :app:`Pyramid` version. See https://webob.org/ for further information. """ + exception = None exc_info = None matchdict = None @@ -201,7 +194,8 @@ class Request( if factory is None: raise AttributeError( 'No session factory registered ' - '(see the Sessions chapter of the Pyramid documentation)') + '(see the Sessions chapter of the Pyramid documentation)' + ) return factory(self) @reify @@ -244,13 +238,17 @@ def route_request_iface(name, bases=()): # zope.interface.interface.Element.__init__ and # https://github.com/Pylons/pyramid/issues/232; as a result, always pass # __doc__ to the InterfaceClass constructor. - iface = InterfaceClass('%s_IRequest' % name, bases=bases, - __doc__="route_request_iface-generated interface") + iface = InterfaceClass( + '%s_IRequest' % name, + bases=bases, + __doc__="route_request_iface-generated interface", + ) # for exception view lookups iface.combined = InterfaceClass( '%s_combined_IRequest' % name, bases=(iface, IRequest), - __doc__='route_request_iface-generated combined interface') + __doc__='route_request_iface-generated combined interface', + ) return iface @@ -258,8 +256,10 @@ def add_global_response_headers(request, headerlist): def add_headers(request, response): for k, v in headerlist: response.headerlist.append((k, v)) + request.add_response_callback(add_headers) + def call_app_with_subpath_as_path_info(request, app): # Copy the request. Use the source request's subpath (if it exists) as # the new request's PATH_INFO. Set the request copy's SCRIPT_NAME to the @@ -280,11 +280,12 @@ def call_app_with_subpath_as_path_info(request, app): new_script_name = '' # compute new_path_info - new_path_info = '/' + '/'.join([native_(x.encode('utf-8'), 'latin-1') - for x in subpath]) + new_path_info = '/' + '/'.join( + [native_(x.encode('utf-8'), 'latin-1') for x in subpath] + ) - if new_path_info != '/': # don't want a sole double-slash - if path_info != '/': # if orig path_info is '/', we're already done + if new_path_info != '/': # don't want a sole double-slash + if path_info != '/': # if orig path_info is '/', we're already done if path_info.endswith('/'): # readd trailing slash stripped by subpath (traversal) # conversion @@ -314,6 +315,7 @@ def call_app_with_subpath_as_path_info(request, app): return new_request.get_response(app) + def apply_request_extensions(request, extensions=None): """Apply request extensions (methods and properties) to an instance of :class:`pyramid.interfaces.IRequest`. This method is dependent on the @@ -331,4 +333,5 @@ def apply_request_extensions(request, extensions=None): setattr(request, name, method) InstancePropertyHelper.apply_properties( - request, extensions.descriptors) + request, extensions.descriptors + ) diff --git a/src/pyramid/resource.py b/src/pyramid/resource.py index 986c75e37..1454114fd 100644 --- a/src/pyramid/resource.py +++ b/src/pyramid/resource.py @@ -1,5 +1,6 @@ """ Backwards compatibility shim module (forever). """ -from pyramid.asset import * # b/w compat +from pyramid.asset import * # b/w compat + resolve_resource_spec = resolve_asset_spec resource_spec_from_abspath = asset_spec_from_abspath abspath_from_resource_spec = abspath_from_asset_spec diff --git a/src/pyramid/response.py b/src/pyramid/response.py index 1e2546ed0..38f9fa1ce 100644 --- a/src/pyramid/response.py +++ b/src/pyramid/response.py @@ -1,8 +1,5 @@ import mimetypes -from os.path import ( - getmtime, - getsize, - ) +from os.path import getmtime, getsize import venusian @@ -18,17 +15,20 @@ def init_mimetypes(mimetypes): return True return False + # See http://bugs.python.org/issue5853 which is a recursion bug # that seems to effect Python 2.6, Python 2.6.1, and 2.6.2 (a fix # has been applied on the Python 2 trunk). init_mimetypes(mimetypes) -_BLOCK_SIZE = 4096 * 64 # 256K +_BLOCK_SIZE = 4096 * 64 # 256K + @implementer(IResponse) class Response(_Response): pass + class FileResponse(Response): """ A Response object that can be used to serve a static file from disk @@ -51,14 +51,21 @@ class FileResponse(Response): binary file. This argument will be ignored if you also leave ``content-type`` as ``None``. """ - def __init__(self, path, request=None, cache_max_age=None, - content_type=None, content_encoding=None): + + def __init__( + self, + path, + request=None, + cache_max_age=None, + content_type=None, + content_encoding=None, + ): if content_type is None: content_type, content_encoding = _guess_type(path) super(FileResponse, self).__init__( conditional_response=True, content_type=content_type, - content_encoding=content_encoding + content_encoding=content_encoding, ) self.last_modified = getmtime(path) content_length = getsize(path) @@ -76,6 +83,7 @@ class FileResponse(Response): if cache_max_age is not None: self.cache_expires = cache_max_age + class FileIter(object): """ A fixed-block-size iterator for use as a WSGI app_iter. @@ -84,6 +92,7 @@ class FileIter(object): ``block_size`` is an optional block size for iteration. """ + def __init__(self, file, block_size=_BLOCK_SIZE): self.file = file self.block_size = block_size @@ -97,7 +106,7 @@ class FileIter(object): raise StopIteration return val - __next__ = next # py3 + __next__ = next # py3 def close(self): self.file.close() @@ -166,7 +175,8 @@ class response_adapter(object): Added the ``_depth`` and ``_category`` arguments. """ - venusian = venusian # for unit testing + + venusian = venusian # for unit testing def __init__(self, *types_or_ifaces, **kwargs): self.types_or_ifaces = types_or_ifaces @@ -180,8 +190,12 @@ class response_adapter(object): config.add_response_adapter(wrapped, type_or_iface, **self.kwargs) def __call__(self, wrapped): - self.venusian.attach(wrapped, self.register, category=self.category, - depth=self.depth + 1) + self.venusian.attach( + wrapped, + self.register, + category=self.category, + depth=self.depth + 1, + ) return wrapped @@ -190,18 +204,14 @@ def _get_response_factory(registry): `pyramid.interfaces.IResponseFactory`. """ response_factory = registry.queryUtility( - IResponseFactory, - default=lambda r: Response() + IResponseFactory, default=lambda r: Response() ) return response_factory def _guess_type(path): - content_type, content_encoding = mimetypes.guess_type( - path, - strict=False - ) + 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 diff --git a/src/pyramid/router.py b/src/pyramid/router.py index 49b7b601b..19641aecd 100644 --- a/src/pyramid/router.py +++ b/src/pyramid/router.py @@ -1,7 +1,4 @@ -from zope.interface import ( - implementer, - providedBy, - ) +from zope.interface import implementer, providedBy from pyramid.interfaces import ( IDebugLogger, @@ -15,14 +12,14 @@ from pyramid.interfaces import ( IRoutesMapper, ITraverser, ITweens, - ) +) from pyramid.events import ( ContextFound, NewRequest, NewResponse, BeforeTraversal, - ) +) from pyramid.httpexceptions import HTTPNotFound from pyramid.request import Request @@ -30,10 +27,8 @@ from pyramid.view import _call_view from pyramid.request import apply_request_extensions from pyramid.threadlocal import RequestContext -from pyramid.traversal import ( - DefaultRootFactory, - ResourceTreeTraverser, - ) +from pyramid.traversal import DefaultRootFactory, ResourceTreeTraverser + @implementer(IRouter) class Router(object): @@ -49,12 +44,13 @@ class Router(object): self.request_factory = q(IRequestFactory, default=Request) self.request_extensions = q(IRequestExtensions) self.execution_policy = q( - IExecutionPolicy, default=default_execution_policy) + IExecutionPolicy, default=default_execution_policy + ) self.orig_handle_request = self.handle_request tweens = q(ITweens) if tweens is not None: self.handle_request = tweens(self.handle_request, registry) - self.root_policy = self.root_factory # b/w compat + self.root_policy = self.root_factory # b/w compat self.registry = registry settings = registry.settings if settings is not None: @@ -82,8 +78,7 @@ class Router(object): match, route = info['match'], info['route'] if route is None: if debug_routematch: - msg = ('no route matched for url %s' % - request.url) + msg = 'no route matched for url %s' % request.url logger and logger.debug(msg) else: attrs['matchdict'] = match @@ -96,20 +91,21 @@ class Router(object): 'path_info: %r, ' 'pattern: %r, ' 'matchdict: %r, ' - 'predicates: %r' % ( + 'predicates: %r' + % ( request.url, route.name, request.path_info, route.pattern, match, - ', '.join([p.text() for p in route.predicates])) + ', '.join([p.text() for p in route.predicates]), ) + ) logger and logger.debug(msg) request.request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) + IRouteRequest, name=route.name, default=IRequest + ) root_factory = route.factory or self.root_factory @@ -137,8 +133,8 @@ class Router(object): tdict['subpath'], tdict['traversed'], tdict['virtual_root'], - tdict['virtual_root_path'] - ) + tdict['virtual_root_path'], + ) attrs.update(tdict) @@ -149,12 +145,8 @@ class Router(object): # find a view callable context_iface = providedBy(context) response = _call_view( - registry, - request, - context, - context_iface, - view_name - ) + registry, request, context, context_iface, view_name + ) if response is None: if self.debug_notfound: @@ -162,11 +154,19 @@ class Router(object): 'debug_notfound of url %s; path_info: %r, ' 'context: %r, view_name: %r, subpath: %r, ' 'traversed: %r, root: %r, vroot: %r, ' - 'vroot_path: %r' % ( - request.url, request.path_info, context, - view_name, subpath, traversed, root, vroot, - vroot_path) + 'vroot_path: %r' + % ( + request.url, + request.path_info, + context, + view_name, + subpath, + traversed, + root, + vroot, + vroot_path, ) + ) logger and logger.debug(msg) else: msg = request.path_info @@ -270,6 +270,7 @@ class Router(object): response = self.execution_policy(environ, self) return response(environ, start_response) + def default_execution_policy(environ, router): with router.request_context(environ) as request: try: diff --git a/src/pyramid/scaffolds/__init__.py b/src/pyramid/scaffolds/__init__.py index 71a220e22..95c51a2d8 100644 --- a/src/pyramid/scaffolds/__init__.py +++ b/src/pyramid/scaffolds/__init__.py @@ -6,11 +6,13 @@ from pyramid.compat import native_ from pyramid.scaffolds.template import Template # API + class PyramidTemplate(Template): """ A class that can be used as a base class for Pyramid scaffolding templates. """ + def pre(self, command, output_dir, vars): """ Overrides :meth:`pyramid.scaffolds.template.Template.pre`, adding several variables to the default variables list (including @@ -26,7 +28,7 @@ class PyramidTemplate(Template): vars['package_logger'] = package_logger return Template.pre(self, command, output_dir, vars) - def post(self, command, output_dir, vars): # pragma: no cover + def post(self, command, output_dir, vars): # pragma: no cover """ Overrides :meth:`pyramid.scaffolds.template.Template.post`, to print "Welcome to Pyramid. Sorry for the convenience." after a successful scaffolding rendering.""" @@ -42,24 +44,29 @@ class PyramidTemplate(Template): Welcome to Pyramid. Sorry for the convenience. %(separator)s - """ % {'separator': separator}) + """ + % {'separator': separator} + ) self.out(msg) return Template.post(self, command, output_dir, vars) - def out(self, msg): # pragma: no cover (replaceable testing hook) + def out(self, msg): # pragma: no cover (replaceable testing hook) print(msg) + class StarterProjectTemplate(PyramidTemplate): _template_dir = 'starter' summary = 'Pyramid starter project using URL dispatch and Jinja2' + class ZODBProjectTemplate(PyramidTemplate): _template_dir = 'zodb' summary = 'Pyramid project using ZODB, traversal, and Chameleon' + class AlchemyProjectTemplate(PyramidTemplate): _template_dir = 'alchemy' summary = ( - 'Pyramid project using SQLAlchemy, SQLite, URL dispatch, and ' - 'Jinja2') + 'Pyramid project using SQLAlchemy, SQLite, URL dispatch, and ' 'Jinja2' + ) diff --git a/src/pyramid/scaffolds/copydir.py b/src/pyramid/scaffolds/copydir.py index 0914bb0d4..31e8dfb9e 100644 --- a/src/pyramid/scaffolds/copydir.py +++ b/src/pyramid/scaffolds/copydir.py @@ -11,7 +11,7 @@ from pyramid.compat import ( native_, url_quote as compat_url_quote, escape, - ) +) fsenc = sys.getfilesystemencoding() @@ -22,9 +22,20 @@ class SkipTemplate(Exception): Raise this exception during the substitution of your template """ -def copy_dir(source, dest, vars, verbosity, simulate, indent=0, - sub_vars=True, interactive=False, overwrite=True, - template_renderer=None, out_=sys.stdout): + +def copy_dir( + source, + dest, + vars, + verbosity, + simulate, + indent=0, + sub_vars=True, + interactive=False, + overwrite=True, + template_renderer=None, + out_=sys.stdout, +): """ Copies the ``source`` directory to the ``dest`` directory. @@ -49,10 +60,12 @@ def copy_dir(source, dest, vars, verbosity, simulate, indent=0, ``template_renderer(content_as_string, vars_as_dict, filename=filename)``. """ + def out(msg): out_.write(msg) out_.write('\n') out_.flush() + # This allows you to use a leading +dot+ in filenames which would # otherwise be skipped because leading dots make the file hidden: vars.setdefault('dot', '.') @@ -80,7 +93,7 @@ def copy_dir(source, dest, vars, verbosity, simulate, indent=0, if verbosity >= 2: reason = pad + reason % {'filename': full} out(reason) - continue # pragma: no cover + continue # pragma: no cover if sub_vars: dest_full = os.path.join(dest, substitute_filename(name, vars)) sub_file = False @@ -90,18 +103,36 @@ def copy_dir(source, dest, vars, verbosity, simulate, indent=0, if use_pkg_resources and pkg_resources.resource_isdir(source[0], full): if verbosity: out('%sRecursing into %s' % (pad, os.path.basename(full))) - copy_dir((source[0], full), dest_full, vars, verbosity, simulate, - indent=indent + 1, sub_vars=sub_vars, - interactive=interactive, overwrite=overwrite, - template_renderer=template_renderer, out_=out_) + copy_dir( + (source[0], full), + dest_full, + vars, + verbosity, + simulate, + indent=indent + 1, + sub_vars=sub_vars, + interactive=interactive, + overwrite=overwrite, + template_renderer=template_renderer, + out_=out_, + ) continue elif not use_pkg_resources and os.path.isdir(full): if verbosity: out('%sRecursing into %s' % (pad, os.path.basename(full))) - copy_dir(full, dest_full, vars, verbosity, simulate, - indent=indent + 1, sub_vars=sub_vars, - interactive=interactive, overwrite=overwrite, - template_renderer=template_renderer, out_=out_) + copy_dir( + full, + dest_full, + vars, + verbosity, + simulate, + indent=indent + 1, + sub_vars=sub_vars, + interactive=interactive, + overwrite=overwrite, + template_renderer=template_renderer, + out_=out_, + ) continue elif use_pkg_resources: content = pkg_resources.resource_string(source[0], full) @@ -111,12 +142,14 @@ def copy_dir(source, dest, vars, verbosity, simulate, indent=0, if sub_file: try: content = substitute_content( - content, vars, filename=full, - template_renderer=template_renderer - ) - except SkipTemplate: - continue # pragma: no cover - if content is None: + content, + vars, + filename=full, + template_renderer=template_renderer, + ) + except SkipTemplate: + continue # pragma: no cover + if content is None: continue # pragma: no cover already_exists = os.path.exists(dest_full) if already_exists: @@ -124,27 +157,33 @@ def copy_dir(source, dest, vars, verbosity, simulate, indent=0, old_content = f.read() if old_content == content: if verbosity: - out('%s%s already exists (same content)' % - (pad, dest_full)) - continue # pragma: no cover + out( + '%s%s already exists (same content)' % (pad, dest_full) + ) + continue # pragma: no cover if interactive: if not query_interactive( - native_(full, fsenc), native_(dest_full, fsenc), - native_(content, fsenc), native_(old_content, fsenc), - simulate=simulate, out_=out_): + native_(full, fsenc), + native_(dest_full, fsenc), + native_(content, fsenc), + native_(old_content, fsenc), + simulate=simulate, + out_=out_, + ): continue elif not overwrite: - continue # pragma: no cover + continue # pragma: no cover if verbosity and use_pkg_resources: out('%sCopying %s to %s' % (pad, full, dest_full)) elif verbosity: out( - '%sCopying %s to %s' % (pad, os.path.basename(full), - dest_full)) + '%sCopying %s to %s' % (pad, os.path.basename(full), dest_full) + ) if not simulate: with open(dest_full, 'wb') as f: f.write(content) + def should_skip_file(name): """ Checks if a file should be skipped based on its name. @@ -164,38 +203,60 @@ def should_skip_file(name): return 'Skipping version control directory %(filename)s' return None + # Overridden on user's request: all_answer = None -def query_interactive(src_fn, dest_fn, src_content, dest_content, - simulate, out_=sys.stdout): + +def query_interactive( + src_fn, dest_fn, src_content, dest_content, simulate, out_=sys.stdout +): def out(msg): out_.write(msg) out_.write('\n') out_.flush() + global all_answer from difflib import unified_diff, context_diff - u_diff = list(unified_diff( - dest_content.splitlines(), - src_content.splitlines(), - dest_fn, src_fn)) - c_diff = list(context_diff( - dest_content.splitlines(), - src_content.splitlines(), - dest_fn, src_fn)) - added = len([l for l in u_diff if l.startswith('+') and - not l.startswith('+++')]) - removed = len([l for l in u_diff if l.startswith('-') and - not l.startswith('---')]) + + u_diff = list( + unified_diff( + dest_content.splitlines(), + src_content.splitlines(), + dest_fn, + src_fn, + ) + ) + c_diff = list( + context_diff( + dest_content.splitlines(), + src_content.splitlines(), + dest_fn, + src_fn, + ) + ) + added = len( + [l for l in u_diff if l.startswith('+') and not l.startswith('+++')] + ) + removed = len( + [l for l in u_diff if l.startswith('-') and not l.startswith('---')] + ) if added > removed: msg = '; %i lines added' % (added - removed) elif removed > added: msg = '; %i lines removed' % (removed - added) else: msg = '' - out('Replace %i bytes with %i bytes (%i/%i lines changed%s)' % ( - len(dest_content), len(src_content), - removed, len(dest_content.splitlines()), msg)) + out( + 'Replace %i bytes with %i bytes (%i/%i lines changed%s)' + % ( + len(dest_content), + len(src_content), + removed, + len(dest_content.splitlines()), + msg, + ) + ) prompt = 'Overwrite %s [y/n/d/B/?] ' % dest_fn while 1: if all_answer is None: @@ -204,6 +265,7 @@ def query_interactive(src_fn, dest_fn, src_content, dest_content, response = all_answer if not response or response[0] == 'b': import shutil + new_dest_fn = dest_fn + '.bak' n = 0 while os.path.exists(new_dest_fn): @@ -230,6 +292,7 @@ def query_interactive(src_fn, dest_fn, src_content, dest_content, else: out(query_usage) + query_usage = """\ Responses: Y(es): Overwrite the file with the new content. @@ -240,39 +303,47 @@ Responses: Type "all Y/N/B" to use Y/N/B for answer to all future questions """ + def makedirs(dir, verbosity, pad): parent = os.path.dirname(os.path.abspath(dir)) if not os.path.exists(parent): makedirs(parent, verbosity, pad) # pragma: no cover os.mkdir(dir) + def substitute_filename(fn, vars): for var, value in vars.items(): fn = fn.replace('+%s+' % var, str(value)) return fn -def substitute_content(content, vars, filename='<string>', - template_renderer=None): + +def substitute_content( + content, vars, filename='<string>', template_renderer=None +): v = standard_vars.copy() v.update(vars) return template_renderer(content, v, filename=filename) + def html_quote(s): if s is None: return '' return escape(str(s), 1) + def url_quote(s): if s is None: return '' return compat_url_quote(str(s)) + def test(conf, true_cond, false_cond=None): if conf: return true_cond else: return false_cond + def skip_template(condition=True, *args): """ Raise SkipTemplate, which causes copydir to skip the template @@ -286,6 +357,7 @@ def skip_template(condition=True, *args): if condition: raise SkipTemplate(*args) + standard_vars = { 'nothing': None, 'html_quote': html_quote, @@ -297,5 +369,4 @@ standard_vars = { 'bool': bool, 'SkipTemplate': SkipTemplate, 'skip_template': skip_template, - } - +} diff --git a/src/pyramid/scaffolds/template.py b/src/pyramid/scaffolds/template.py index e5098e815..60b543842 100644 --- a/src/pyramid/scaffolds/template.py +++ b/src/pyramid/scaffolds/template.py @@ -6,19 +6,18 @@ import re import sys import os -from pyramid.compat import ( - native_, - bytes_, - ) +from pyramid.compat import native_, bytes_ from pyramid.scaffolds import copydir fsenc = sys.getfilesystemencoding() + class Template(object): """ Inherit from this base class and override methods to use the Pyramid scaffolding system.""" - copydir = copydir # for testing + + copydir = copydir # for testing _template_dir = None def __init__(self, name): @@ -36,7 +35,10 @@ class Template(object): try: return bytes_( substitute_escaped_double_braces( - substitute_double_braces(content, TypeMapper(vars))), fsenc) + substitute_double_braces(content, TypeMapper(vars)) + ), + fsenc, + ) except Exception as e: _add_except(e, ' in file %s' % filename) raise @@ -54,7 +56,8 @@ class Template(object): construct a path. If _template_dir is a tuple, it should be a 2-element tuple: ``(package_name, package_relative_path)``.""" assert self._template_dir is not None, ( - "Template %r didn't set _template_dir" % self) + "Template %r didn't set _template_dir" % self + ) if isinstance(self._template_dir, tuple): return self._template_dir else: @@ -65,13 +68,13 @@ class Template(object): self.write_files(command, output_dir, vars) self.post(command, output_dir, vars) - def pre(self, command, output_dir, vars): # pragma: no cover + def pre(self, command, output_dir, vars): # pragma: no cover """ Called before template is applied. """ pass - def post(self, command, output_dir, vars): # pragma: no cover + def post(self, command, output_dir, vars): # pragma: no cover """ Called after template is applied. """ @@ -95,15 +98,15 @@ class Template(object): overwrite=command.args.overwrite, indent=1, template_renderer=self.render_template, - ) + ) - def makedirs(self, dir): # pragma: no cover + def makedirs(self, dir): # pragma: no cover return os.makedirs(dir) - def exists(self, path): # pragma: no cover + def exists(self, path): # pragma: no cover return os.path.exists(path) - def out(self, msg): # pragma: no cover + def out(self, msg): # pragma: no cover print(msg) # hair for exit with usage when paster create is used under 1.3 instead @@ -113,13 +116,15 @@ class Template(object): # required_templates tuple is required to allow it to get as far as # calling check_vars. required_templates = () + def check_vars(self, vars, other): raise RuntimeError( 'Under Pyramid 1.3, you should use the "pcreate" command rather ' - 'than "paster create"') + 'than "paster create"' + ) -class TypeMapper(dict): +class TypeMapper(dict): def __getitem__(self, item): options = item.split('|') for op in options[:-1]: @@ -135,6 +140,7 @@ class TypeMapper(dict): else: return str(value) + def eval_with_catch(expr, vars): try: return eval(expr, vars) @@ -142,23 +148,32 @@ def eval_with_catch(expr, vars): _add_except(e, 'in expression %r' % expr) raise + double_brace_pattern = re.compile(r'{{(?P<braced>.*?)}}') + def substitute_double_braces(content, values): def double_bracerepl(match): value = match.group('braced').strip() return values[value] + return double_brace_pattern.sub(double_bracerepl, content) -escaped_double_brace_pattern = re.compile(r'\\{\\{(?P<escape_braced>[^\\]*?)\\}\\}') + +escaped_double_brace_pattern = re.compile( + r'\\{\\{(?P<escape_braced>[^\\]*?)\\}\\}' +) + def substitute_escaped_double_braces(content): def escaped_double_bracerepl(match): value = match.group('escape_braced').strip() return "{{%(value)s}}" % locals() + return escaped_double_brace_pattern.sub(escaped_double_bracerepl, content) -def _add_except(exc, info): # pragma: no cover + +def _add_except(exc, info): # pragma: no cover if not hasattr(exc, 'args') or exc.args is None: return args = list(exc.args) @@ -168,5 +183,3 @@ def _add_except(exc, info): # pragma: no cover args = [info] exc.args = tuple(args) return - - diff --git a/src/pyramid/scaffolds/tests.py b/src/pyramid/scaffolds/tests.py index 44680a464..cb8842dbe 100644 --- a/src/pyramid/scaffolds/tests.py +++ b/src/pyramid/scaffolds/tests.py @@ -15,12 +15,12 @@ class TemplateTest(object): def make_venv(self, directory): # pragma: no cover import virtualenv from virtualenv import Logger + logger = Logger([(Logger.level_for_integer(2), sys.stdout)]) virtualenv.logger = logger - virtualenv.create_environment(directory, - site_packages=False, - clear=False, - unzip_setuptools=True) + virtualenv.create_environment( + directory, site_packages=False, clear=False, unzip_setuptools=True + ) def install(self, tmpl_name): # pragma: no cover try: @@ -36,14 +36,18 @@ class TemplateTest(object): os.chdir('Dingle') subprocess.check_call([pip, 'install', '.[testing]']) if tmpl_name == 'alchemy': - populate = os.path.join(self.directory, 'bin', - 'initialize_Dingle_db') + populate = os.path.join( + self.directory, 'bin', 'initialize_Dingle_db' + ) subprocess.check_call([populate, 'development.ini']) - subprocess.check_call([ - os.path.join(self.directory, 'bin', 'py.test')]) + subprocess.check_call( + [os.path.join(self.directory, 'bin', 'py.test')] + ) pserve = os.path.join(self.directory, 'bin', 'pserve') - for ininame, hastoolbar in (('development.ini', True), - ('production.ini', False)): + for ininame, hastoolbar in ( + ('development.ini', True), + ('production.ini', False), + ): proc = subprocess.Popen([pserve, ininame]) try: time.sleep(5) @@ -66,10 +70,10 @@ class TemplateTest(object): shutil.rmtree(self.directory) os.chdir(self.old_cwd) -if __name__ == '__main__': # pragma: no cover + +if __name__ == '__main__': # pragma: no cover templates = ['starter', 'alchemy', 'zodb'] for name in templates: test = TemplateTest() test.install(name) - diff --git a/src/pyramid/scripting.py b/src/pyramid/scripting.py index 087b55ccb..cbf9d5e32 100644 --- a/src/pyramid/scripting.py +++ b/src/pyramid/scripting.py @@ -1,16 +1,14 @@ from pyramid.config import global_registries from pyramid.exceptions import ConfigurationError -from pyramid.interfaces import ( - IRequestFactory, - IRootFactory, - ) +from pyramid.interfaces import IRequestFactory, IRootFactory from pyramid.request import Request from pyramid.request import apply_request_extensions from pyramid.threadlocal import RequestContext from pyramid.traversal import DefaultRootFactory + def get_root(app, request=None): """ Return a tuple composed of ``(root, closer)`` when provided a :term:`router` instance as the ``app`` argument. The ``root`` @@ -29,11 +27,14 @@ def get_root(app, request=None): request.registry = registry ctx = RequestContext(request) ctx.begin() + def closer(): ctx.end() + root = app.root_factory(request) return root, closer + def prepare(request=None, registry=None): """ This function pushes data onto the Pyramid threadlocal stack (request and registry), making those objects 'current'. It @@ -80,9 +81,11 @@ def prepare(request=None, registry=None): if registry is None: registry = getattr(request, 'registry', global_registries.last) if registry is None: - raise ConfigurationError('No valid Pyramid applications could be ' - 'found, make sure one has been created ' - 'before trying to activate it.') + raise ConfigurationError( + 'No valid Pyramid applications could be ' + 'found, make sure one has been created ' + 'before trying to activate it.' + ) if request is None: request = _make_request('/', registry) # NB: even though _make_request might have already set registry on @@ -92,10 +95,13 @@ def prepare(request=None, registry=None): ctx = RequestContext(request) ctx.begin() apply_request_extensions(request) + def closer(): ctx.end() - root_factory = registry.queryUtility(IRootFactory, - default=DefaultRootFactory) + + root_factory = registry.queryUtility( + IRootFactory, default=DefaultRootFactory + ) root = root_factory(request) if getattr(request, 'context', None) is None: request.context = root @@ -107,6 +113,7 @@ def prepare(request=None, registry=None): root_factory=root_factory, ) + class AppEnvironment(dict): def __enter__(self): return self @@ -114,6 +121,7 @@ class AppEnvironment(dict): def __exit__(self, type, value, traceback): self['closer']() + def _make_request(path, registry=None): """ Return a :meth:`pyramid.request.Request` object anchored at a given path. The object returned will be generated from the supplied diff --git a/src/pyramid/scripts/common.py b/src/pyramid/scripts/common.py index f4b8027db..9181eea8e 100644 --- a/src/pyramid/scripts/common.py +++ b/src/pyramid/scripts/common.py @@ -1,5 +1,6 @@ import plaster + def parse_vars(args): """ Given variables like ``['a=b', 'c=d']`` turns it into ``{'a': @@ -8,13 +9,12 @@ def parse_vars(args): result = {} for arg in args: if '=' not in arg: - raise ValueError( - 'Variable assignment %r invalid (no "=")' - % arg) + raise ValueError('Variable assignment %r invalid (no "=")' % arg) name, value = arg.split('=', 1) result[name] = value return result + def get_config_loader(config_uri): """ Find a ``plaster.ILoader`` object supporting the "wsgi" protocol. diff --git a/src/pyramid/scripts/pcreate.py b/src/pyramid/scripts/pcreate.py index a6db520ce..f3dffefef 100644 --- a/src/pyramid/scripts/pcreate.py +++ b/src/pyramid/scripts/pcreate.py @@ -33,60 +33,88 @@ https://github.com/Pylons/?q=cookiecutter """, formatter_class=argparse.RawDescriptionHelpFormatter, ) - parser.add_argument('-s', '--scaffold', - dest='scaffold_name', - action='append', - help=("Add a scaffold to the create process " - "(multiple -s args accepted)")) - parser.add_argument('-t', '--template', - dest='scaffold_name', - action='append', - help=('A backwards compatibility alias for ' - '-s/--scaffold. Add a scaffold to the ' - 'create process (multiple -t args accepted)')) - parser.add_argument('-l', '--list', - dest='list', - action='store_true', - help="List all available scaffold names") - parser.add_argument('--list-templates', - dest='list', - action='store_true', - help=("A backwards compatibility alias for -l/--list. " - "List all available scaffold names.")) - parser.add_argument('--package-name', - dest='package_name', - action='store', - help='Package name to use. The name provided is ' - 'assumed to be a valid Python package name, and ' - 'will not be validated. By default the package ' - 'name is derived from the value of ' - 'output_directory.') - parser.add_argument('--simulate', - dest='simulate', - action='store_true', - help='Simulate but do no work') - parser.add_argument('--overwrite', - dest='overwrite', - action='store_true', - help='Always overwrite') - parser.add_argument('--interactive', - dest='interactive', - action='store_true', - help='When a file would be overwritten, interrogate ' - '(this is the default, but you may specify it to ' - 'override --overwrite)') - parser.add_argument('--ignore-conflicting-name', - dest='force_bad_name', - action='store_true', - default=False, - help='Do create a project even if the chosen name ' - 'is the name of an already existing / importable ' - 'package.') - parser.add_argument('output_directory', - nargs='?', - default=None, - help='The directory where the project will be ' - 'created.') + parser.add_argument( + '-s', + '--scaffold', + dest='scaffold_name', + action='append', + help=( + "Add a scaffold to the create process " + "(multiple -s args accepted)" + ), + ) + parser.add_argument( + '-t', + '--template', + dest='scaffold_name', + action='append', + help=( + 'A backwards compatibility alias for ' + '-s/--scaffold. Add a scaffold to the ' + 'create process (multiple -t args accepted)' + ), + ) + parser.add_argument( + '-l', + '--list', + dest='list', + action='store_true', + help="List all available scaffold names", + ) + parser.add_argument( + '--list-templates', + dest='list', + action='store_true', + help=( + "A backwards compatibility alias for -l/--list. " + "List all available scaffold names." + ), + ) + parser.add_argument( + '--package-name', + dest='package_name', + action='store', + help='Package name to use. The name provided is ' + 'assumed to be a valid Python package name, and ' + 'will not be validated. By default the package ' + 'name is derived from the value of ' + 'output_directory.', + ) + parser.add_argument( + '--simulate', + dest='simulate', + action='store_true', + help='Simulate but do no work', + ) + parser.add_argument( + '--overwrite', + dest='overwrite', + action='store_true', + help='Always overwrite', + ) + parser.add_argument( + '--interactive', + dest='interactive', + action='store_true', + help='When a file would be overwritten, interrogate ' + '(this is the default, but you may specify it to ' + 'override --overwrite)', + ) + parser.add_argument( + '--ignore-conflicting-name', + dest='force_bad_name', + action='store_true', + default=False, + help='Do create a project even if the chosen name ' + 'is the name of an already existing / importable ' + 'package.', + ) + parser.add_argument( + 'output_directory', + nargs='?', + default=None, + help='The directory where the project will be ' 'created.', + ) pyramid_dist = pkg_resources.get_distribution("pyramid") @@ -123,7 +151,8 @@ https://github.com/Pylons/?q=cookiecutter project_name = os.path.basename(os.path.split(output_dir)[1]) if self.args.package_name is None: pkg_name = _bad_chars_re.sub( - '', project_name.lower().replace('-', '_')) + '', project_name.lower().replace('-', '_') + ) safe_name = pkg_resources.safe_name(project_name) else: pkg_name = self.args.package_name @@ -170,9 +199,14 @@ https://github.com/Pylons/?q=cookiecutter max_name = max([len(t.name) for t in scaffolds]) self.out('Available scaffolds:') for scaffold in scaffolds: - self.out(' %s:%s %s' % ( - scaffold.name, - ' ' * (max_name - len(scaffold.name)), scaffold.summary)) + self.out( + ' %s:%s %s' + % ( + scaffold.name, + ' ' * (max_name - len(scaffold.name)), + scaffold.summary, + ) + ) else: self.out('No scaffolds available') return 0 @@ -186,8 +220,10 @@ https://github.com/Pylons/?q=cookiecutter scaffold = scaffold_class(entry.name) scaffolds.append(scaffold) except Exception as e: # pragma: no cover - self.out('Warning: could not load entry point %s (%s: %s)' % ( - entry.name, e.__class__.__name__, e)) + self.out( + 'Warning: could not load entry point %s (%s: %s)' + % (entry.name, e.__class__.__name__, e) + ) return scaffolds def out(self, msg): # pragma: no cover @@ -196,8 +232,10 @@ https://github.com/Pylons/?q=cookiecutter def validate_input(self): if not self.args.scaffold_name: - self.out('You must provide at least one scaffold name: ' - '-s <scaffold name>') + self.out( + 'You must provide at least one scaffold name: ' + '-s <scaffold name>' + ) self.out('') self.show_scaffolds() return False @@ -213,11 +251,14 @@ https://github.com/Pylons/?q=cookiecutter pkg_name = self.project_vars['package'] if pkg_name == 'site' and not self.args.force_bad_name: - self.out('The package name "site" has a special meaning in ' - 'Python. Are you sure you want to use it as your ' - 'project\'s name?') - return self.confirm_bad_name('Really use "{0}"?: '.format( - pkg_name)) + self.out( + 'The package name "site" has a special meaning in ' + 'Python. Are you sure you want to use it as your ' + 'project\'s name?' + ) + return self.confirm_bad_name( + 'Really use "{0}"?: '.format(pkg_name) + ) # check if pkg_name can be imported (i.e. already exists in current # $PYTHON_PATH, if so - let the user confirm @@ -232,8 +273,10 @@ https://github.com/Pylons/?q=cookiecutter if self.args.force_bad_name: return True - self.out('A package named "{0}" already exists, are you sure you want ' - 'to use it as your project\'s name?'.format(pkg_name)) + self.out( + 'A package named "{0}" already exists, are you sure you want ' + 'to use it as your project\'s name?'.format(pkg_name) + ) return self.confirm_bad_name('Really use "{0}"?: '.format(pkg_name)) def confirm_bad_name(self, prompt): # pragma: no cover @@ -241,11 +284,14 @@ https://github.com/Pylons/?q=cookiecutter return answer.strip().lower() == 'y' def _warn_pcreate_deprecated(self): - self.out('''\ + self.out( + '''\ Note: As of Pyramid 1.8, this command is deprecated. Use a specific cookiecutter instead: https://github.com/pylons/?query=cookiecutter -''') +''' + ) + if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/scripts/pdistreport.py b/src/pyramid/scripts/pdistreport.py index 1952e5d39..3ace9451e 100644 --- a/src/pyramid/scripts/pdistreport.py +++ b/src/pyramid/scripts/pdistreport.py @@ -4,19 +4,27 @@ import pkg_resources import argparse from operator import itemgetter -def out(*args): # pragma: no cover + +def out(*args): # pragma: no cover for arg in args: sys.stdout.write(arg) sys.stdout.write(' ') sys.stdout.write('\n') + def get_parser(): parser = argparse.ArgumentParser( - description="Show Python distribution versions and locations in use") + description="Show Python distribution versions and locations in use" + ) return parser -def main(argv=sys.argv, pkg_resources=pkg_resources, platform=platform.platform, - out=out): + +def main( + argv=sys.argv, + pkg_resources=pkg_resources, + platform=platform.platform, + out=out, +): # all args except argv are for unit testing purposes only parser = get_parser() parser.parse_args(argv[1:]) @@ -24,11 +32,13 @@ def main(argv=sys.argv, pkg_resources=pkg_resources, platform=platform.platform, for distribution in pkg_resources.working_set: name = distribution.project_name packages.append( - {'version': distribution.version, - 'lowername': name.lower(), - 'name': name, - 'location':distribution.location} - ) + { + 'version': distribution.version, + 'lowername': name.lower(), + 'name': name, + 'location': distribution.location, + } + ) packages = sorted(packages, key=itemgetter('lowername')) pyramid_version = pkg_resources.get_distribution('pyramid').version plat = platform() @@ -39,5 +49,6 @@ def main(argv=sys.argv, pkg_resources=pkg_resources, platform=platform.platform, out(' ', package['name'], package['version']) out(' ', package['location']) -if __name__ == '__main__': # pragma: no cover + +if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/scripts/prequest.py b/src/pyramid/scripts/prequest.py index f0681afd7..e8f5ff8b3 100644 --- a/src/pyramid/scripts/prequest.py +++ b/src/pyramid/scripts/prequest.py @@ -8,10 +8,12 @@ from pyramid.request import Request from pyramid.scripts.common import get_config_loader from pyramid.scripts.common import parse_vars + def main(argv=sys.argv, quiet=False): command = PRequestCommand(argv, quiet) return command.run() + class PRequestCommand(object): description = """\ Submit a HTTP request to a web application. @@ -48,15 +50,16 @@ class PRequestCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) + ) parser.add_argument( - '-n', '--app-name', + '-n', + '--app-name', dest='app_name', metavar='NAME', help=( "Load the named application from the config file (default 'main')" ), - ) + ) parser.add_argument( '--header', dest='headers', @@ -67,47 +70,55 @@ class PRequestCommand(object): ), ) parser.add_argument( - '-d', '--display-headers', + '-d', + '--display-headers', dest='display_headers', action='store_true', - help='Display status and headers before the response body' - ) + help='Display status and headers before the response body', + ) parser.add_argument( - '-m', '--method', + '-m', + '--method', dest='method', - choices=['GET', 'HEAD', 'POST', 'PUT', 'PATCH','DELETE', - 'PROPFIND', 'OPTIONS'], + choices=[ + 'GET', + 'HEAD', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'PROPFIND', + 'OPTIONS', + ], help='Request method type (GET, POST, PUT, PATCH, DELETE, ' - 'PROPFIND, OPTIONS)', - ) + 'PROPFIND, OPTIONS)', + ) parser.add_argument( - '-l', '--login', + '-l', + '--login', dest='login', help='HTTP basic auth username:password pair', - ) + ) parser.add_argument( 'config_uri', nargs='?', default=None, help='The URI to the configuration file.', - ) + ) parser.add_argument( - 'path_info', - nargs='?', - default=None, - help='The path of the request.', - ) + 'path_info', nargs='?', default=None, help='The path of the request.' + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) _get_config_loader = staticmethod(get_config_loader) stdin = sys.stdin @@ -116,7 +127,7 @@ class PRequestCommand(object): self.quiet = quiet self.args = self.parser.parse_args(argv[1:]) - def out(self, msg): # pragma: no cover + def out(self, msg): # pragma: no cover if not self.quiet: print(msg) @@ -153,7 +164,8 @@ class PRequestCommand(object): if ':' not in item: self.out( "Bad --header=%s option, value must be in the form " - "'name:value'" % item) + "'name:value'" % item + ) return 2 name, value = item.split(':', 1) headers[name] = value.strip() @@ -162,13 +174,13 @@ class PRequestCommand(object): environ = { 'REQUEST_METHOD': request_method, - 'SCRIPT_NAME': '', # may be empty if app is at the root + 'SCRIPT_NAME': '', # may be empty if app is at the root 'PATH_INFO': path, 'SERVER_NAME': 'localhost', # always mandatory - 'SERVER_PORT': '80', # always mandatory + 'SERVER_PORT': '80', # always mandatory 'SERVER_PROTOCOL': 'HTTP/1.0', 'CONTENT_TYPE': 'text/plain', - 'REMOTE_ADDR':'127.0.0.1', + 'REMOTE_ADDR': '127.0.0.1', 'wsgi.run_once': True, 'wsgi.multithread': False, 'wsgi.multiprocess': False, @@ -178,7 +190,7 @@ class PRequestCommand(object): 'QUERY_STRING': qs, 'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1', 'paste.command_request': True, - } + } if request_method in ('POST', 'PUT', 'PATCH'): environ['wsgi.input'] = self.stdin @@ -203,5 +215,6 @@ class PRequestCommand(object): self.out(response.body) return 0 -if __name__ == '__main__': # pragma: no cover + +if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/scripts/proutes.py b/src/pyramid/scripts/proutes.py index 69d61ae8f..2bce7d1de 100644 --- a/src/pyramid/scripts/proutes.py +++ b/src/pyramid/scripts/proutes.py @@ -110,7 +110,7 @@ def _get_view_module(view_callable): if original_view.package_name is not None: return '%s:%s' % ( original_view.package_name, - original_view.docroot + original_view.docroot, ) else: return original_view.docroot @@ -122,10 +122,7 @@ def _get_view_module(view_callable): # for them and remove this logic view_name = str(view_callable) - view_module = '%s.%s' % ( - view_callable.__module__, - view_name, - ) + view_module = '%s.%s' % (view_callable.__module__, view_name) # If pyramid wraps something in wsgiapp or wsgiapp2 decorators # that is currently returned as pyramid.router.decorator, lets @@ -139,24 +136,17 @@ def _get_view_module(view_callable): def get_route_data(route, registry): pattern = _get_pattern(route) - request_iface = registry.queryUtility( - IRouteRequest, - name=route.name - ) + request_iface = registry.queryUtility(IRouteRequest, name=route.name) route_request_methods = None view_request_methods_order = [] view_request_methods = {} view_callable = None - route_intr = registry.introspector.get( - 'routes', route.name - ) + route_intr = registry.introspector.get('routes', route.name) if request_iface is None: - return [ - (route.name, _get_pattern(route), UNKNOWN_KEY, ANY_KEY) - ] + return [(route.name, _get_pattern(route), UNKNOWN_KEY, ANY_KEY)] view_callables = _find_views(registry, request_iface, Interface, '') if view_callables: @@ -188,7 +178,7 @@ def get_route_data(route, registry): view_callable = getattr(view['callable'], view['attr']) view_module = '%s.%s' % ( _get_view_module(view['callable']), - view['attr'] + view['attr'], ) else: view_callable = view['callable'] @@ -217,17 +207,11 @@ def get_route_data(route, registry): for view_module in view_request_methods_order: methods = view_request_methods[view_module] - request_methods = _get_request_methods( - route_request_methods, - methods - ) + request_methods = _get_request_methods(route_request_methods, methods) - final_routes.append(( - route.name, - pattern, - view_module, - request_methods, - )) + final_routes.append( + (route.name, pattern, view_module, request_methods) + ) return final_routes @@ -251,43 +235,49 @@ class PRoutesCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) - parser.add_argument('-g', '--glob', - action='store', - dest='glob', - default='', - help='Display routes matching glob pattern') - - parser.add_argument('-f', '--format', - action='store', - dest='format', - default='', - help=('Choose which columns to display, this will ' - 'override the format key in the [proutes] ini ' - 'section')) + ) + parser.add_argument( + '-g', + '--glob', + action='store', + dest='glob', + default='', + help='Display routes matching glob pattern', + ) + + parser.add_argument( + '-f', + '--format', + action='store', + dest='format', + default='', + help=( + 'Choose which columns to display, this will ' + 'override the format key in the [proutes] ini ' + 'section' + ), + ) parser.add_argument( 'config_uri', nargs='?', default=None, help='The URI to the configuration file.', - ) + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) def __init__(self, argv, quiet=False): self.args = self.parser.parse_args(argv[1:]) self.quiet = quiet - self.available_formats = [ - 'name', 'pattern', 'view', 'method' - ] + self.available_formats = ['name', 'pattern', 'view', 'method'] self.column_format = self.available_formats def validate_formats(self, formats): @@ -296,10 +286,7 @@ class PRoutesCommand(object): if fmt not in self.available_formats: invalid_formats.append(fmt) - msg = ( - 'You provided invalid formats %s, ' - 'Available formats are %s' - ) + msg = 'You provided invalid formats %s, ' 'Available formats are %s' if invalid_formats: msg = msg % (invalid_formats, self.available_formats) @@ -321,6 +308,7 @@ class PRoutesCommand(object): def _get_mapper(self, registry): from pyramid.config import Configurator + config = Configurator(registry=registry) return config.get_routes_mapper() @@ -361,25 +349,29 @@ class PRoutesCommand(object): if len(routes) == 0: return 0 - mapped_routes = [{ - 'name': 'Name', - 'pattern': 'Pattern', - 'view': 'View', - 'method': 'Method' - },{ - 'name': '----', - 'pattern': '-------', - 'view': '----', - 'method': '------' - }] + mapped_routes = [ + { + 'name': 'Name', + 'pattern': 'Pattern', + 'view': 'View', + 'method': 'Method', + }, + { + 'name': '----', + 'pattern': '-------', + 'view': '----', + 'method': '------', + }, + ] for route in routes: route_data = get_route_data(route, registry) for name, pattern, view, method in route_data: if self.args.glob: - match = (fnmatch.fnmatch(name, self.args.glob) or - fnmatch.fnmatch(pattern, self.args.glob)) + match = fnmatch.fnmatch( + name, self.args.glob + ) or fnmatch.fnmatch(pattern, self.args.glob) if not match: continue @@ -395,12 +387,14 @@ class PRoutesCommand(object): if len(method) > max_method: max_method = len(method) - mapped_routes.append({ - 'name': name, - 'pattern': pattern, - 'view': view, - 'method': method - }) + mapped_routes.append( + { + 'name': name, + 'pattern': pattern, + 'view': view, + 'method': method, + } + ) fmt = _get_print_format( self.column_format, max_name, max_pattern, max_view, max_method diff --git a/src/pyramid/scripts/pserve.py b/src/pyramid/scripts/pserve.py index 8ee6e1467..581479d65 100644 --- a/src/pyramid/scripts/pserve.py +++ b/src/pyramid/scripts/pserve.py @@ -46,67 +46,86 @@ class PServeCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) + ) parser.add_argument( - '-n', '--app-name', + '-n', + '--app-name', dest='app_name', metavar='NAME', - help="Load the named application (default main)") + help="Load the named application (default main)", + ) parser.add_argument( - '-s', '--server', + '-s', + '--server', dest='server', metavar='SERVER_TYPE', - help="Use the named server.") + help="Use the named server.", + ) parser.add_argument( '--server-name', dest='server_name', metavar='SECTION_NAME', - help=("Use the named server as defined in the configuration file " - "(default: main)")) + help=( + "Use the named server as defined in the configuration file " + "(default: main)" + ), + ) parser.add_argument( '--reload', dest='reload', action='store_true', - help="Use auto-restart file monitor") + help="Use auto-restart file monitor", + ) parser.add_argument( '--reload-interval', dest='reload_interval', default=1, - help=("Seconds between checking files (low number can cause " - "significant CPU usage)")) + help=( + "Seconds between checking files (low number can cause " + "significant CPU usage)" + ), + ) parser.add_argument( - '-b', '--browser', + '-b', + '--browser', dest='browser', action='store_true', - help=("Open a web browser to the server url. The server url is " - "determined from the 'open_url' setting in the 'pserve' " - "section of the configuration file.")) + help=( + "Open a web browser to the server url. The server url is " + "determined from the 'open_url' setting in the 'pserve' " + "section of the configuration file." + ), + ) parser.add_argument( - '-v', '--verbose', + '-v', + '--verbose', default=default_verbosity, dest='verbose', action='count', - help="Set verbose level (default " + str(default_verbosity) + ")") + help="Set verbose level (default " + str(default_verbosity) + ")", + ) parser.add_argument( - '-q', '--quiet', + '-q', + '--quiet', action='store_const', const=0, dest='verbose', - help="Suppress verbose output") + help="Suppress verbose output", + ) parser.add_argument( 'config_uri', nargs='?', default=None, help='The URI to the configuration file.', - ) + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) _get_config_loader = staticmethod(get_config_loader) # for testing @@ -187,18 +206,23 @@ class PServeCommand(object): if not url: url = self.guess_server_url( - server_loader, server_name, config_vars) + server_loader, server_name, config_vars + ) if not url: - self.out('WARNING: could not determine the server\'s url to ' - 'open the browser. To fix this set the "open_url" ' - 'setting in the [pserve] section of the ' - 'configuration file.') + self.out( + 'WARNING: could not determine the server\'s url to ' + 'open the browser. To fix this set the "open_url" ' + 'setting in the [pserve] section of the ' + 'configuration file.' + ) else: + def open_browser(): time.sleep(1) webbrowser.open(url) + t = threading.Thread(target=open_browser) t.setDaemon(True) t.start() @@ -210,7 +234,7 @@ class PServeCommand(object): 'pyramid.scripts.pserve.main', reload_interval=int(self.args.reload_interval), verbose=self.args.verbose, - worker_kwargs=self.worker_kwargs + worker_kwargs=self.worker_kwargs, ) return 0 @@ -250,6 +274,7 @@ class PServeCommand(object): # For paste.deploy server instantiation (egg:pyramid#wsgiref) def wsgiref_server_runner(wsgi_app, global_conf, **kw): # pragma: no cover from wsgiref.simple_server import make_server + host = kw.get('host', '0.0.0.0') port = int(kw.get('port', 8080)) server = make_server(host, port, wsgi_app) @@ -259,11 +284,18 @@ def wsgiref_server_runner(wsgi_app, global_conf, **kw): # pragma: no cover # For paste.deploy server instantiation (egg:pyramid#cherrypy) def cherrypy_server_runner( - app, global_conf=None, host='127.0.0.1', port=None, - ssl_pem=None, protocol_version=None, numthreads=None, - server_name=None, max=None, request_queue_size=None, - timeout=None - ): # pragma: no cover + app, + global_conf=None, + host='127.0.0.1', + port=None, + ssl_pem=None, + protocol_version=None, + numthreads=None, + server_name=None, + max=None, + request_queue_size=None, + timeout=None, +): # pragma: no cover """ Entry point for CherryPy's WSGI server @@ -346,8 +378,7 @@ def cherrypy_server_runner( except ImportError: from cherrypy.wsgiserver import CherryPyWSGIServer as WSGIServer - server = WSGIServer(bind_addr, app, - server_name=server_name, **kwargs) + 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 @@ -368,8 +399,10 @@ def cherrypy_server_runner( try: protocol = is_ssl and 'https' or 'http' if host == '0.0.0.0': - print('serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % - (port, protocol, port)) + print( + 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' + % (port, protocol, port) + ) else: print('serving on %s://%s:%s' % (protocol, host, port)) server.start() diff --git a/src/pyramid/scripts/pshell.py b/src/pyramid/scripts/pshell.py index 4898eb39f..e63114d18 100644 --- a/src/pyramid/scripts/pshell.py +++ b/src/pyramid/scripts/pshell.py @@ -16,6 +16,7 @@ from pyramid.settings import aslist from pyramid.scripts.common import get_config_loader from pyramid.scripts.common import parse_vars + def main(argv=sys.argv, quiet=False): command = PShellCommand(argv, quiet) return command.run() @@ -49,38 +50,52 @@ class PShellCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) - parser.add_argument('-p', '--python-shell', - action='store', - dest='python_shell', - default='', - help=('Select the shell to use. A list of possible ' - 'shells is available using the --list-shells ' - 'option.')) - parser.add_argument('-l', '--list-shells', - dest='list', - action='store_true', - help='List all available shells.') - parser.add_argument('--setup', - dest='setup', - help=("A callable that will be passed the environment " - "before it is made available to the shell. This " - "option will override the 'setup' key in the " - "[pshell] ini section.")) - parser.add_argument('config_uri', - nargs='?', - default=None, - help='The URI to the configuration file.') + ) + parser.add_argument( + '-p', + '--python-shell', + action='store', + dest='python_shell', + default='', + help=( + 'Select the shell to use. A list of possible ' + 'shells is available using the --list-shells ' + 'option.' + ), + ) + parser.add_argument( + '-l', + '--list-shells', + dest='list', + action='store_true', + help='List all available shells.', + ) + parser.add_argument( + '--setup', + dest='setup', + help=( + "A callable that will be passed the environment " + "before it is made available to the shell. This " + "option will override the 'setup' key in the " + "[pshell] ini section." + ), + ) + parser.add_argument( + 'config_uri', + nargs='?', + default=None, + help='The URI to the configuration file.', + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) - default_runner = python_shell_runner # testing + default_runner = python_shell_runner # testing loaded_objects = {} object_help = {} @@ -107,7 +122,7 @@ class PShellCommand(object): self.loaded_objects[k] = self.resolver.maybe_resolve(v) self.object_help[k] = v - def out(self, msg): # pragma: no cover + def out(self, msg): # pragma: no cover if not self.quiet: print(msg) @@ -152,8 +167,9 @@ class PShellCommand(object): env_help['root'] = 'Root of the default resource tree.' env_help['registry'] = 'Active Pyramid registry.' env_help['request'] = 'Active request object.' - env_help['root_factory'] = ( - 'Default root factory used to create `root`.') + env_help[ + 'root_factory' + ] = 'Default root factory used to create `root`.' # load the pshell section of the ini file env.update(self.loaded_objects) @@ -236,6 +252,7 @@ class PShellCommand(object): # by default prioritize all shells above python preferred_shells = [k for k in shells.keys() if k != 'python'] max_weight = len(preferred_shells) + def order(x): # invert weight to reverse sort the list # (closer to the front is higher priority) @@ -243,6 +260,7 @@ class PShellCommand(object): return preferred_shells.index(x[0].lower()) - max_weight except ValueError: return 1 + sorted_shells = sorted(shells.items(), key=order) if len(sorted_shells) > 0: @@ -266,5 +284,5 @@ class PShellCommand(object): return shell -if __name__ == '__main__': # pragma: no cover +if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/scripts/ptweens.py b/src/pyramid/scripts/ptweens.py index d5cbebe12..e6a5c5ac7 100644 --- a/src/pyramid/scripts/ptweens.py +++ b/src/pyramid/scripts/ptweens.py @@ -10,10 +10,12 @@ from pyramid.paster import bootstrap from pyramid.paster import setup_logging from pyramid.scripts.common import parse_vars + def main(argv=sys.argv, quiet=False): command = PTweensCommand(argv, quiet) return command.run() + class PTweensCommand(object): description = """\ Print all implicit and explicit tween objects used by a Pyramid @@ -31,25 +33,27 @@ class PTweensCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) + ) - parser.add_argument('config_uri', - nargs='?', - default=None, - help='The URI to the configuration file.') + parser.add_argument( + 'config_uri', + nargs='?', + default=None, + help='The URI to the configuration file.', + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) stdout = sys.stdout - bootstrap = staticmethod(bootstrap) # testing - setup_logging = staticmethod(setup_logging) # testing + bootstrap = staticmethod(bootstrap) # testing + setup_logging = staticmethod(setup_logging) # testing def __init__(self, argv, quiet=False): self.quiet = quiet @@ -57,10 +61,11 @@ class PTweensCommand(object): def _get_tweens(self, registry): from pyramid.config import Configurator + config = Configurator(registry=registry) return config.registry.queryUtility(ITweens) - def out(self, msg): # pragma: no cover + def out(self, msg): # pragma: no cover if not self.quiet: print(msg) @@ -86,8 +91,10 @@ class PTweensCommand(object): if tweens is not None: explicit = tweens.explicit if explicit: - self.out('"pyramid.tweens" config value set ' - '(explicitly ordered tweens used)') + self.out( + '"pyramid.tweens" config value set ' + '(explicitly ordered tweens used)' + ) self.out('') self.out('Explicit Tween Chain (used)') self.out('') @@ -97,13 +104,16 @@ class PTweensCommand(object): self.out('') self.show_chain(tweens.implicit()) else: - self.out('"pyramid.tweens" config value NOT set ' - '(implicitly ordered tweens used)') + self.out( + '"pyramid.tweens" config value NOT set ' + '(implicitly ordered tweens used)' + ) self.out('') self.out('Implicit Tween Chain') self.out('') self.show_chain(tweens.implicit()) return 0 -if __name__ == '__main__': # pragma: no cover + +if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/scripts/pviews.py b/src/pyramid/scripts/pviews.py index c0df2f078..891dc4709 100644 --- a/src/pyramid/scripts/pviews.py +++ b/src/pyramid/scripts/pviews.py @@ -9,10 +9,12 @@ from pyramid.request import Request from pyramid.scripts.common import parse_vars from pyramid.view import _find_views + def main(argv=sys.argv, quiet=False): command = PViewsCommand(argv, quiet) return command.run() + class PViewsCommand(object): description = """\ Print, for a given URL, the views that might match. Underneath each @@ -31,38 +33,41 @@ class PViewsCommand(object): parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, - ) + ) - parser.add_argument('config_uri', - nargs='?', - default=None, - help='The URI to the configuration file.') + parser.add_argument( + 'config_uri', + nargs='?', + default=None, + help='The URI to the configuration file.', + ) - parser.add_argument('url', - nargs='?', - default=None, - help='The path info portion of the URL.') + parser.add_argument( + 'url', + nargs='?', + default=None, + help='The path info portion of the URL.', + ) parser.add_argument( 'config_vars', nargs='*', default=(), help="Variables required by the config file. For example, " - "`http_port=%%(http_port)s` would expect `http_port=8080` to be " - "passed here.", - ) + "`http_port=%%(http_port)s` would expect `http_port=8080` to be " + "passed here.", + ) - - bootstrap = staticmethod(bootstrap) # testing - setup_logging = staticmethod(setup_logging) # testing + bootstrap = staticmethod(bootstrap) # testing + setup_logging = staticmethod(setup_logging) # testing def __init__(self, argv, quiet=False): self.quiet = quiet self.args = self.parser.parse_args(argv[1:]) - def out(self, msg): # pragma: no cover + def out(self, msg): # pragma: no cover if not self.quiet: print(msg) - + def _find_multi_routes(self, mapper, request): infos = [] path = request.environ['PATH_INFO'] @@ -70,7 +75,7 @@ class PViewsCommand(object): for route in mapper.get_routes(): match = route.match(path) if match is not None: - info = {'match':match, 'route':route} + info = {'match': match, 'route': route} infos.append(info) return infos @@ -99,22 +104,17 @@ class PViewsCommand(object): @implementer(IMultiView) class RoutesMultiView(object): - def __init__(self, infos, context_iface, root_factory, request): self.views = [] for info in infos: match, route = info['match'], info['route'] if route is not None: request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) + IRouteRequest, name=route.name, default=IRequest + ) views = _find_views( - request.registry, - request_iface, - context_iface, - '' - ) + request.registry, request_iface, context_iface, '' + ) if not views: continue view = views[0] @@ -148,9 +148,8 @@ class PViewsCommand(object): attrs['matched_route'] = route request.environ['bfg.routes.matchdict'] = match request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) + IRouteRequest, name=route.name, default=IRequest + ) root_factory = route.factory or root_factory if len(infos) > 1: routes_multiview = infos @@ -171,11 +170,8 @@ class PViewsCommand(object): context_iface = providedBy(context) if routes_multiview is None: views = _find_views( - request.registry, - request_iface, - context_iface, - view_name, - ) + request.registry, request_iface, context_iface, view_name + ) if views: view = views[0] else: @@ -186,11 +182,8 @@ class PViewsCommand(object): # routes are not registered with a view name if view is None: views = _find_views( - request.registry, - request_iface, - context_iface, - '', - ) + request.registry, request_iface, context_iface, '' + ) if views: view = views[0] else: @@ -285,5 +278,6 @@ class PViewsCommand(object): env['closer']() return 0 -if __name__ == '__main__': # pragma: no cover + +if __name__ == '__main__': # pragma: no cover sys.exit(main() or 0) diff --git a/src/pyramid/security.py b/src/pyramid/security.py index 0bdca090b..9e256f73c 100644 --- a/src/pyramid/security.py +++ b/src/pyramid/security.py @@ -7,7 +7,7 @@ from pyramid.interfaces import ( ISecuredView, IView, IViewClassifier, - ) +) from pyramid.compat import map_ from pyramid.threadlocal import get_current_registry @@ -17,6 +17,7 @@ Authenticated = 'system.Authenticated' Allow = 'Allow' Deny = 'Deny' + class AllPermissionsList(object): """ Stand in 'permission list' to represent all permissions """ @@ -29,22 +30,26 @@ class AllPermissionsList(object): def __eq__(self, other): return isinstance(other, self.__class__) + ALL_PERMISSIONS = AllPermissionsList() DENY_ALL = (Deny, Everyone, ALL_PERMISSIONS) NO_PERMISSION_REQUIRED = '__no_permission_required__' + def _get_registry(request): try: reg = request.registry except AttributeError: - reg = get_current_registry() # b/c + reg = get_current_registry() # b/c return reg + def _get_authentication_policy(request): registry = _get_registry(request) return registry.queryUtility(IAuthenticationPolicy) + def has_permission(permission, context, request): """ A function that calls :meth:`pyramid.request.Request.has_permission` @@ -56,15 +61,16 @@ def has_permission(permission, context, request): .. versionchanged:: 1.5a3 If context is None, then attempt to use the context attribute of self; if not set, then the AttributeError is propagated. - """ + """ return request.has_permission(permission, context) + deprecated( 'has_permission', 'As of Pyramid 1.5 the "pyramid.security.has_permission" API is now ' 'deprecated. It will be removed in Pyramid 1.8. Use the ' - '"has_permission" method of the Pyramid request instead.' - ) + '"has_permission" method of the Pyramid request instead.', +) def authenticated_userid(request): @@ -74,15 +80,17 @@ def authenticated_userid(request): .. deprecated:: 1.5 Use :attr:`pyramid.request.Request.authenticated_userid` instead. - """ + """ return request.authenticated_userid + deprecated( 'authenticated_userid', 'As of Pyramid 1.5 the "pyramid.security.authenticated_userid" API is now ' 'deprecated. It will be removed in Pyramid 1.8. Use the ' - '"authenticated_userid" attribute of the Pyramid request instead.' - ) + '"authenticated_userid" attribute of the Pyramid request instead.', +) + def unauthenticated_userid(request): """ @@ -91,15 +99,17 @@ def unauthenticated_userid(request): .. deprecated:: 1.5 Use :attr:`pyramid.request.Request.unauthenticated_userid` instead. - """ + """ return request.unauthenticated_userid + deprecated( 'unauthenticated_userid', 'As of Pyramid 1.5 the "pyramid.security.unauthenticated_userid" API is ' 'now deprecated. It will be removed in Pyramid 1.8. Use the ' - '"unauthenticated_userid" attribute of the Pyramid request instead.' - ) + '"unauthenticated_userid" attribute of the Pyramid request instead.', +) + def effective_principals(request): """ @@ -108,15 +118,17 @@ def effective_principals(request): .. deprecated:: 1.5 Use :attr:`pyramid.request.Request.effective_principals` instead. - """ + """ return request.effective_principals + deprecated( 'effective_principals', 'As of Pyramid 1.5 the "pyramid.security.effective_principals" API is ' 'now deprecated. It will be removed in Pyramid 1.8. Use the ' - '"effective_principals" attribute of the Pyramid request instead.' - ) + '"effective_principals" attribute of the Pyramid request instead.', +) + def remember(request, userid, **kw): """ @@ -154,6 +166,7 @@ def remember(request, userid, **kw): return [] return policy.remember(request, userid, **kw) + def forget(request): """ Return a sequence of header tuples (e.g. ``[('Set-Cookie', @@ -172,12 +185,13 @@ def forget(request): If no :term:`authentication policy` is in use, this function will always return an empty sequence. - """ + """ policy = _get_authentication_policy(request) if policy is None: return [] return policy.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 @@ -201,6 +215,7 @@ def principals_allowed_by_permission(context, permission): return [Everyone] return policy.principals_allowed_by_permission(context, permission) + def view_execution_permitted(context, request, name=''): """ If the view specified by ``context`` and ``name`` is protected by a :term:`permission`, check the permission associated with the @@ -222,12 +237,15 @@ def view_execution_permitted(context, request, name=''): if view is None: view = reg.adapters.lookup(provides, IView, name=name) if view is None: - raise TypeError('No registered view satisfies the constraints. ' - 'It would not make sense to claim that this view ' - '"is" or "is not" permitted.') + raise TypeError( + 'No registered view satisfies the constraints. ' + 'It would not make sense to claim that this view ' + '"is" or "is not" permitted.' + ) return Allowed( - 'Allowed: view name %r in context %r (no permission defined)' % - (name, context)) + 'Allowed: view name %r in context %r (no permission defined)' + % (name, context) + ) return view.__permitted__(context, request) @@ -255,9 +273,12 @@ class PermitsResult(int): return self.msg def __repr__(self): - return '<%s instance at %s with msg %r>' % (self.__class__.__name__, - id(self), - self.msg) + return '<%s instance at %s with msg %r>' % ( + self.__class__.__name__, + id(self), + self.msg, + ) + class Denied(PermitsResult): """ @@ -268,8 +289,10 @@ class Denied(PermitsResult): the deny. """ + boolval = 0 + class Allowed(PermitsResult): """ An instance of ``Allowed`` is returned when a security-related @@ -279,8 +302,10 @@ class Allowed(PermitsResult): the allow. """ + boolval = 1 + class ACLPermitsResult(PermitsResult): def __new__(cls, ace, acl, permission, principals, context): """ @@ -294,17 +319,12 @@ class ACLPermitsResult(PermitsResult): searched. """ - fmt = ('%s permission %r via ACE %r in ACL %r on context %r for ' - 'principals %r') + fmt = ( + '%s permission %r via ACE %r in ACL %r on context %r for ' + 'principals %r' + ) inst = PermitsResult.__new__( - cls, - fmt, - cls.__name__, - permission, - ace, - acl, - context, - principals, + cls, fmt, cls.__name__, permission, ace, acl, context, principals ) inst.permission = permission inst.ace = ace @@ -313,6 +333,7 @@ class ACLPermitsResult(PermitsResult): inst.context = context return inst + class ACLDenied(ACLPermitsResult, Denied): """ An instance of ``ACLDenied`` is a specialization of @@ -326,6 +347,7 @@ class ACLDenied(ACLPermitsResult, Denied): """ + class ACLAllowed(ACLPermitsResult, Allowed): """ An instance of ``ACLAllowed`` is a specialization of @@ -339,8 +361,8 @@ class ACLAllowed(ACLPermitsResult, Allowed): """ -class AuthenticationAPIMixin(object): +class AuthenticationAPIMixin(object): def _get_authentication_policy(self): reg = _get_registry(self) return reg.queryUtility(IAuthenticationPolicy) @@ -389,8 +411,8 @@ class AuthenticationAPIMixin(object): return [Everyone] return policy.effective_principals(self) -class AuthorizationAPIMixin(object): +class AuthorizationAPIMixin(object): def has_permission(self, permission, context=None): """ Given a permission and an optional context, returns an instance of :data:`pyramid.security.Allowed` if the permission is granted to this @@ -421,7 +443,9 @@ class AuthorizationAPIMixin(object): return Allowed('No authentication policy in use.') authz_policy = reg.queryUtility(IAuthorizationPolicy) if authz_policy is None: - raise ValueError('Authentication policy registered without ' - 'authorization policy') # should never happen + raise ValueError( + 'Authentication policy registered without ' + 'authorization policy' + ) # should never happen principals = authn_policy.effective_principals(self) return authz_policy.permits(context, principals, permission) diff --git a/src/pyramid/session.py b/src/pyramid/session.py index b953fa184..9d4ef6dbb 100644 --- a/src/pyramid/session.py +++ b/src/pyramid/session.py @@ -9,22 +9,10 @@ import warnings from zope.deprecation import deprecated from zope.interface import implementer -from webob.cookies import ( - JSONSerializer, - SignedSerializer, -) +from webob.cookies import JSONSerializer, SignedSerializer -from pyramid.compat import ( - pickle, - PY2, - text_, - bytes_, - native_, - ) -from pyramid.csrf import ( - check_csrf_origin, - check_csrf_token, -) +from pyramid.compat import pickle, PY2, text_, bytes_, native_ +from pyramid.csrf import check_csrf_origin, check_csrf_token from pyramid.interfaces import ISession from pyramid.util import strings_differ @@ -33,25 +21,31 @@ from pyramid.util import strings_differ def manage_accessed(wrapped): """ Decorator which causes a cookie to be renewed when an accessor method is called.""" + def accessed(session, *arg, **kw): session.accessed = now = int(time.time()) if session._reissue_time is not None: if now - session.renewed > session._reissue_time: session.changed() return wrapped(session, *arg, **kw) + accessed.__doc__ = wrapped.__doc__ return accessed + def manage_changed(wrapped): """ Decorator which causes a cookie to be set when a setter method is called.""" + def changed(session, *arg, **kw): session.accessed = int(time.time()) session.changed() return wrapped(session, *arg, **kw) + changed.__doc__ = wrapped.__doc__ return changed + def signed_serialize(data, secret): """ Serialize any pickleable structure (``data``) and sign it using the ``secret`` (must be a string). Return the @@ -82,6 +76,7 @@ def signed_serialize(data, secret): sig = hmac.new(secret, pickled, hashlib.sha1).hexdigest() return sig + native_(base64.b64encode(pickled)) + deprecated( 'signed_serialize', 'This function will be removed in Pyramid 2.0. It is using pickle-based ' @@ -89,6 +84,7 @@ deprecated( 'attacks.', ) + def signed_deserialize(serialized, secret, hmac=hmac): """ Deserialize the value returned from ``signed_serialize``. If the value cannot be deserialized for any reason, a @@ -111,8 +107,10 @@ def signed_deserialize(serialized, secret, hmac=hmac): """ # hmac parameterized only for unit tests try: - input_sig, pickled = (bytes_(serialized[:40]), - base64.b64decode(bytes_(serialized[40:]))) + input_sig, pickled = ( + bytes_(serialized[:40]), + base64.b64decode(bytes_(serialized[40:])), + ) except (binascii.Error, TypeError) as e: # Badly formed data can make base64 die raise ValueError('Badly formed base64 data: %s' % e) @@ -131,6 +129,7 @@ def signed_deserialize(serialized, secret, hmac=hmac): return pickle.loads(pickled) + deprecated( 'signed_deserialize', 'This function will be removed in Pyramid 2.0. It is using pickle-based ' @@ -149,6 +148,7 @@ class PickleSerializer(object): Defaults to :attr:`pickle.HIGHEST_PROTOCOL`. """ + def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): self.protocol = protocol @@ -180,7 +180,7 @@ def BaseCookieSessionFactory( timeout=1200, reissue_time=0, set_on_exception=True, - ): +): """ Configure a :term:`session factory` which will provide cookie-based sessions. The return value of this function is a :term:`session factory`, @@ -280,7 +280,9 @@ def BaseCookieSessionFactory( _cookie_samesite = samesite _cookie_on_exception = set_on_exception _timeout = timeout if timeout is None else int(timeout) - _reissue_time = reissue_time if reissue_time is None else int(reissue_time) + _reissue_time = ( + reissue_time if reissue_time is None else int(reissue_time) + ) # dirty flag _dirty = False @@ -330,13 +332,15 @@ def BaseCookieSessionFactory( def changed(self): if not self._dirty: self._dirty = True + def set_cookie_callback(request, response): self._set_cookie(response) - self.request = None # explicitly break cycle for gc + self.request = None # explicitly break cycle for gc + self.request.add_response_callback(set_cookie_callback) def invalidate(self): - self.clear() # XXX probably needs to unset cookie + self.clear() # XXX probably needs to unset cookie # non-modifying dictionary methods get = manage_accessed(dict.get) @@ -398,16 +402,18 @@ def BaseCookieSessionFactory( def _set_cookie(self, response): if not self._cookie_on_exception: exception = getattr(self.request, 'exception', None) - if exception is not None: # dont set a cookie during exceptions + if ( + exception is not None + ): # dont set a cookie during exceptions return False - cookieval = native_(serializer.dumps( - (self.accessed, self.created, dict(self)) - )) + cookieval = native_( + serializer.dumps((self.accessed, self.created, dict(self))) + ) if len(cookieval) > 4064: raise ValueError( - 'Cookie value is too long to store (%s bytes)' % - len(cookieval) - ) + 'Cookie value is too long to store (%s bytes)' + % len(cookieval) + ) response.set_cookie( self._cookie_name, value=cookieval, @@ -417,7 +423,7 @@ def BaseCookieSessionFactory( secure=self._cookie_secure, httponly=self._cookie_httponly, samesite=self._cookie_samesite, - ) + ) return True return CookieSession @@ -436,7 +442,7 @@ def UnencryptedCookieSessionFactoryConfig( cookie_on_exception=True, signed_serialize=signed_serialize, signed_deserialize=signed_deserialize, - ): +): """ .. deprecated:: 1.5 Use :func:`pyramid.session.SignedCookieSessionFactory` instead. @@ -530,18 +536,19 @@ def UnencryptedCookieSessionFactoryConfig( httponly=cookie_httponly, samesite=cookie_samesite, timeout=timeout, - reissue_time=0, # to keep session.accessed == session.renewed + reissue_time=0, # to keep session.accessed == session.renewed set_on_exception=cookie_on_exception, ) + deprecated( 'UnencryptedCookieSessionFactoryConfig', 'The UnencryptedCookieSessionFactoryConfig callable is deprecated as of ' 'Pyramid 1.5. Use ``pyramid.session.SignedCookieSessionFactory`` instead.' ' Caveat: Cookies generated using SignedCookieSessionFactory are not ' 'compatible with cookies generated using UnencryptedCookieSessionFactory, ' - 'so existing user session data will be destroyed if you switch to it.' - ) + 'so existing user session data will be destroyed if you switch to it.', +) def SignedCookieSessionFactory( @@ -559,7 +566,7 @@ def SignedCookieSessionFactory( hashalg='sha512', salt='pyramid.session.', serializer=None, - ): +): """ .. versionadded:: 1.5 @@ -681,11 +688,8 @@ def SignedCookieSessionFactory( ) signed_serializer = SignedSerializer( - secret, - salt, - hashalg, - serializer=serializer, - ) + secret, salt, hashalg, serializer=serializer + ) return BaseCookieSessionFactory( signed_serializer, @@ -701,12 +705,17 @@ def SignedCookieSessionFactory( set_on_exception=set_on_exception, ) + check_csrf_origin = check_csrf_origin # api -deprecated('check_csrf_origin', - 'pyramid.session.check_csrf_origin is deprecated as of Pyramid ' - '1.9. Use pyramid.csrf.check_csrf_origin instead.') +deprecated( + 'check_csrf_origin', + 'pyramid.session.check_csrf_origin is deprecated as of Pyramid ' + '1.9. Use pyramid.csrf.check_csrf_origin instead.', +) check_csrf_token = check_csrf_token # api -deprecated('check_csrf_token', - 'pyramid.session.check_csrf_token is deprecated as of Pyramid ' - '1.9. Use pyramid.csrf.check_csrf_token instead.') +deprecated( + 'check_csrf_token', + 'pyramid.session.check_csrf_token is deprecated as of Pyramid ' + '1.9. Use pyramid.csrf.check_csrf_token instead.', +) diff --git a/src/pyramid/settings.py b/src/pyramid/settings.py index 8a498d572..af9433840 100644 --- a/src/pyramid/settings.py +++ b/src/pyramid/settings.py @@ -3,6 +3,7 @@ from pyramid.compat import string_types truthy = frozenset(('t', 'true', 'y', 'yes', 'on', '1')) falsey = frozenset(('f', 'false', 'n', 'no', 'off', '0')) + def asbool(s): """ Return the boolean value ``True`` if the case-lowered value of string input ``s`` is a :term:`truthy string`. If ``s`` is already one of the @@ -14,11 +15,13 @@ def asbool(s): s = str(s).strip() return s.lower() in truthy + def aslist_cronly(value): if isinstance(value, string_types): value = filter(None, [x.strip() for x in value.splitlines()]) return list(value) + def aslist(value, flatten=True): """ Return a list of strings, separating the input based on newlines and, if flatten=True (the default), also split on spaces within diff --git a/src/pyramid/static.py b/src/pyramid/static.py index 70fdf877b..58ad97a46 100644 --- a/src/pyramid/static.py +++ b/src/pyramid/static.py @@ -2,47 +2,25 @@ import json import os -from os.path import ( - getmtime, - normcase, - normpath, - join, - isdir, - exists, - ) - -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 os.path import getmtime, normcase, normpath, join, isdir, exists + +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 -from pyramid.response import ( - _guess_type, - FileResponse, -) +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 :app:`Pyramid` :term:`view callable`; this view will serve @@ -88,8 +66,14 @@ class static_view(object): to override the assets it contains. """ - def __init__(self, root_dir, cache_max_age=3600, package_name=None, - use_subpath=False, index='index.html'): + def __init__( + self, + root_dir, + cache_max_age=3600, + package_name=None, + use_subpath=False, + index='index.html', + ): # package_name is for bw compat; it is preferred to pass in a # package-relative path as root_dir # (e.g. ``anotherpackage:foo/static``). @@ -113,20 +97,21 @@ class static_view(object): if path is None: raise HTTPNotFound('Out of bounds: %s' % request.url) - if self.package_name: # package resource + if self.package_name: # package resource resource_path = '%s/%s' % (self.docroot.rstrip('/'), path) if resource_isdir(self.package_name, resource_path): if not request.path_url.endswith('/'): self.add_slash_redirect(request) resource_path = '%s/%s' % ( - resource_path.rstrip('/'), self.index + resource_path.rstrip('/'), + self.index, ) if not resource_exists(self.package_name, resource_path): raise HTTPNotFound(request.url) filepath = resource_filename(self.package_name, resource_path) - else: # filesystem file + else: # filesystem file # os.path.normpath converts / to \ on windows filepath = normcase(normpath(join(self.norm_docroot, path))) @@ -139,8 +124,12 @@ class static_view(object): content_type, content_encoding = _guess_type(filepath) return FileResponse( - filepath, request, self.cache_max_age, - content_type, content_encoding=None) + filepath, + request, + self.cache_max_age, + content_type, + content_encoding=None, + ) def add_slash_redirect(self, request): url = request.path_url + '/' @@ -149,14 +138,19 @@ class static_view(object): url = url + '?' + qs raise HTTPMovedPermanently(url) + _seps = set(['/', os.sep]) + + def _contains_slash(item): for sep in _seps: if sep in item: return True + _has_insecure_pathelement = set(['..', '.', '']).intersection + @lru_cache(1000) def _secure_path(path_tuple): if _has_insecure_pathelement(path_tuple): @@ -166,9 +160,10 @@ 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 = slash.join(path_tuple) # will be unicode return encoded + class QueryStringCacheBuster(object): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which adds @@ -182,6 +177,7 @@ class QueryStringCacheBuster(object): .. versionadded:: 1.6 """ + def __init__(self, param='x'): self.param = param @@ -194,6 +190,7 @@ class QueryStringCacheBuster(object): kw['_query'] = tuple(query) + ((self.param, token),) return subpath, kw + class QueryStringConstantCacheBuster(QueryStringCacheBuster): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which adds @@ -207,6 +204,7 @@ class QueryStringConstantCacheBuster(QueryStringCacheBuster): .. versionadded:: 1.6 """ + def __init__(self, token, param='x'): super(QueryStringConstantCacheBuster, self).__init__(param=param) self._token = token @@ -214,6 +212,7 @@ class QueryStringConstantCacheBuster(QueryStringCacheBuster): def tokenize(self, request, subpath, kw): return self._token + class ManifestCacheBuster(object): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which @@ -255,13 +254,15 @@ class ManifestCacheBuster(object): .. versionadded:: 1.6 """ - exists = staticmethod(exists) # testing - getmtime = staticmethod(getmtime) # testing + + exists = staticmethod(exists) # testing + getmtime = staticmethod(getmtime) # testing def __init__(self, manifest_spec, reload=False): package_name = caller_package().__name__ self.manifest_path = abspath_from_asset_spec( - manifest_spec, package_name) + manifest_spec, package_name + ) self.reload = reload self._mtime = None diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index 4986c0e27..e2549f0b9 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -2,22 +2,11 @@ import copy import os from contextlib import contextmanager -from zope.interface import ( - implementer, - alsoProvides, - ) +from zope.interface import implementer, alsoProvides -from pyramid.interfaces import ( - IRequest, - ISession, - ) +from pyramid.interfaces import IRequest, ISession -from pyramid.compat import ( - PY3, - PYPY, - class_types, - text_, - ) +from pyramid.compat import PY3, PYPY, class_types, text_ from pyramid.config import Configurator from pyramid.decorator import reify @@ -30,12 +19,9 @@ from pyramid.security import ( Everyone, AuthenticationAPIMixin, AuthorizationAPIMixin, - ) +) -from pyramid.threadlocal import ( - get_current_registry, - manager, - ) +from pyramid.threadlocal import get_current_registry, manager from pyramid.i18n import LocalizerRequestMixin from pyramid.request import CallbackMethodsMixin @@ -46,17 +32,27 @@ from pyramid.view import ViewMethodsMixin _marker = object() + class DummyRootFactory(object): __parent__ = None __name__ = None + def __init__(self, request): if 'bfg.routes.matchdict' in request: self.__dict__.update(request['bfg.routes.matchdict']) + class DummySecurityPolicy(object): """ A standin for both an IAuthentication and IAuthorization policy """ - def __init__(self, userid=None, groupids=(), permissive=True, - remember_result=None, forget_result=None): + + def __init__( + self, + userid=None, + groupids=(), + permissive=True, + remember_result=None, + forget_result=None, + ): self.userid = userid self.groupids = groupids self.permissive = permissive @@ -95,6 +91,7 @@ class DummySecurityPolicy(object): def principals_allowed_by_permission(self, context, permission): return self.effective_principals(None) + class DummyTemplateRenderer(object): """ An instance of this class is returned from @@ -103,6 +100,7 @@ class DummyTemplateRenderer(object): assertion which compares data passed to the renderer by the view function against expected key/value pairs. """ + def __init__(self, string_response=''): self._received = {} self._string_response = string_response @@ -113,9 +111,11 @@ class DummyTemplateRenderer(object): # source code, *everything* is an API! def _get_string_response(self): return self._string_response + def _set_string_response(self, response): self._string_response = response self._implementation.response = response + string_response = property(_get_string_response, _set_string_response) def implementation(self): @@ -151,19 +151,23 @@ class DummyTemplateRenderer(object): if myval is _marker: raise AssertionError( 'A value for key "%s" was not passed to the renderer' - % k) + % k + ) if myval != v: raise AssertionError( - '\nasserted value for %s: %r\nactual value: %r' % ( - k, v, myval)) + '\nasserted value for %s: %r\nactual value: %r' + % (k, v, myval) + ) return True class DummyResource: """ A dummy :app:`Pyramid` :term:`resource` object.""" - def __init__(self, __name__=None, __parent__=None, __provides__=None, - **kw): + + def __init__( + self, __name__=None, __parent__=None, __provides__=None, **kw + ): """ The resource's ``__name__`` attribute will be set to the value of the ``__name__`` argument, and the resource's ``__parent__`` attribute will be set to the value of the @@ -250,12 +254,15 @@ class DummyResource: inst.__parent__ = __parent__ return inst -DummyModel = DummyResource # b/w compat (forever) + +DummyModel = DummyResource # b/w compat (forever) + @implementer(ISession) class DummySession(dict): created = None new = True + def changed(self): pass @@ -286,6 +293,7 @@ class DummySession(dict): token = self.new_csrf_token() return token + @implementer(IRequest) class DummyRequest( URLMethodsMixin, @@ -295,7 +303,7 @@ class DummyRequest( AuthenticationAPIMixin, AuthorizationAPIMixin, ViewMethodsMixin, - ): +): """ A DummyRequest object (incompletely) imitates a :term:`request` object. The ``params``, ``environ``, ``headers``, ``path``, and @@ -322,6 +330,7 @@ class DummyRequest( a Request, use the :class:`pyramid.request.Request` class itself rather than this class while writing tests. """ + method = 'GET' application_url = 'http://example.com' host = 'example.com:80' @@ -333,8 +342,16 @@ class DummyRequest( _registry = None request_iface = IRequest - def __init__(self, params=None, environ=None, headers=None, path='/', - cookies=None, post=None, **kw): + def __init__( + self, + params=None, + environ=None, + headers=None, + path='/', + cookies=None, + post=None, + **kw + ): if environ is None: environ = {} if params is None: @@ -369,7 +386,7 @@ class DummyRequest( self.context = None self.root = None self.virtual_root = None - self.marshalled = params # repoze.monty + self.marshalled = params # repoze.monty self.session = DummySession() self.__dict__.update(kw) @@ -391,11 +408,18 @@ class DummyRequest( f = _get_response_factory(self.registry) return f(self) + have_zca = True -def setUp(registry=None, request=None, hook_zca=True, autocommit=True, - settings=None, package=None): +def setUp( + registry=None, + request=None, + hook_zca=True, + autocommit=True, + settings=None, + package=None, +): """ Set :app:`Pyramid` registry and request thread locals for the duration of a single unit test. @@ -462,8 +486,9 @@ def setUp(registry=None, request=None, hook_zca=True, autocommit=True, registry = Registry('testing') if package is None: package = caller_package() - config = Configurator(registry=registry, autocommit=autocommit, - package=package) + config = Configurator( + registry=registry, autocommit=autocommit, package=package + ) if settings is None: settings = {} if getattr(registry, 'settings', None) is None: @@ -486,12 +511,13 @@ def setUp(registry=None, request=None, hook_zca=True, autocommit=True, global have_zca try: have_zca and hook_zca and config.hook_zca() - except ImportError: # pragma: no cover + except ImportError: # pragma: no cover # (dont choke on not being able to import z.component) have_zca = False config.begin(request=request) return config + def tearDown(unhook_zca=True): """Undo the effects of :func:`pyramid.testing.setUp`. Use this function in the ``tearDown`` method of a unit test that uses @@ -507,8 +533,9 @@ def tearDown(unhook_zca=True): if unhook_zca and have_zca: try: from zope.component import getSiteManager + getSiteManager.reset() - except ImportError: # pragma: no cover + except ImportError: # pragma: no cover have_zca = False info = manager.pop() manager.clear() @@ -524,6 +551,7 @@ def tearDown(unhook_zca=True): # understand, let's not blow up pass + def cleanUp(*arg, **kw): """ An alias for :func:`pyramid.testing.setUp`. """ package = kw.get('package', None) @@ -532,6 +560,7 @@ def cleanUp(*arg, **kw): kw['package'] = package return setUp(*arg, **kw) + class DummyRendererFactory(object): """ Registered by :meth:`pyramid.config.Configurator.testing_add_renderer` as @@ -540,9 +569,10 @@ class DummyRendererFactory(object): wild believing they can register either. The ``factory`` argument passed to this constructor is usually the *real* template renderer factory, found when ``testing_add_renderer`` is called.""" + def __init__(self, name, factory): self.name = name - self.factory = factory # the "real" renderer factory reg'd previously + self.factory = factory # the "real" renderer factory reg'd previously self.renderers = {} def add(self, spec, renderer): @@ -562,8 +592,9 @@ class DummyRendererFactory(object): if self.factory: renderer = self.factory(info) else: - raise KeyError('No testing renderer registered for %r' % - spec) + raise KeyError( + 'No testing renderer registered for %r' % spec + ) return renderer @@ -571,15 +602,19 @@ class MockTemplate(object): def __init__(self, response): self._received = {} self.response = response + def __getattr__(self, attrname): return self + def __getitem__(self, attrname): return self + def __call__(self, *arg, **kw): self._received.update(kw) return self.response -def skip_on(*platforms): # pragma: no cover + +def skip_on(*platforms): # pragma: no cover skip = False for platform in platforms: if skip_on.os_name.startswith(platform): @@ -596,22 +631,26 @@ def skip_on(*platforms): # pragma: no cover else: return func else: + def wrapper(*args, **kw): if skip: return return func(*args, **kw) + wrapper.__name__ = func.__name__ wrapper.__doc__ = func.__doc__ return wrapper + return decorator -skip_on.os_name = os.name # for testing + + +skip_on.os_name = os.name # for testing + @contextmanager -def testConfig(registry=None, - request=None, - hook_zca=True, - autocommit=True, - settings=None): +def testConfig( + registry=None, request=None, hook_zca=True, autocommit=True, settings=None +): """Returns a context manager for test set up. This context manager calls :func:`pyramid.testing.setUp` when @@ -630,11 +669,13 @@ def testConfig(registry=None, req = DummyRequest() resp = myview(req) """ - config = setUp(registry=registry, - request=request, - hook_zca=hook_zca, - autocommit=autocommit, - settings=settings) + config = setUp( + registry=registry, + request=request, + hook_zca=hook_zca, + autocommit=autocommit, + settings=settings, + ) try: yield config finally: diff --git a/src/pyramid/threadlocal.py b/src/pyramid/threadlocal.py index e8f825715..7eca5b0f0 100644 --- a/src/pyramid/threadlocal.py +++ b/src/pyramid/threadlocal.py @@ -2,6 +2,7 @@ import threading from pyramid.registry import global_registry + class ThreadLocalManager(threading.local): def __init__(self, default=None): # http://code.google.com/p/google-app-engine-django/issues/detail?id=119 @@ -15,7 +16,7 @@ class ThreadLocalManager(threading.local): def push(self, info): self.stack.append(info) - set = push # b/c + set = push # b/c def pop(self): if self.stack: @@ -30,11 +31,14 @@ class ThreadLocalManager(threading.local): def clear(self): self.stack[:] = [] + def defaults(): return {'request': None, 'registry': global_registry} + manager = ThreadLocalManager(default=defaults) + def get_current_request(): """ Return the currently active request or ``None`` if no request @@ -49,7 +53,10 @@ def get_current_request(): """ return manager.get()['request'] -def get_current_registry(context=None): # context required by getSiteManager API + +def get_current_registry( + context=None +): # context required by getSiteManager API """ Return the currently active :term:`application registry` or the global application registry if no request is currently active. @@ -63,6 +70,7 @@ def get_current_registry(context=None): # context required by getSiteManager API """ return manager.get()['registry'] + class RequestContext(object): def __init__(self, request): self.request = request diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index d8f4690fd..322f57ed6 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -6,7 +6,7 @@ from pyramid.interfaces import ( IRequestFactory, ITraverser, VH_ROOT_KEY, - ) +) from pyramid.compat import ( PY2, @@ -19,18 +19,19 @@ from pyramid.compat import ( decode_path_info, unquote_bytes_to_wsgi, lru_cache, - ) +) from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage from pyramid.threadlocal import get_current_registry -PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob +PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob PATH_SAFE = PATH_SEGMENT_SAFE + "/" empty = text_('') + def find_root(resource): """ Find the root node in the resource tree to which ``resource`` belongs. Note that ``resource`` should be :term:`location`-aware. @@ -43,6 +44,7 @@ def find_root(resource): break return resource + def find_resource(resource, path): """ Given a resource object and a string or tuple representing a path (such as the return value of :func:`pyramid.traversal.resource_path` or @@ -101,7 +103,9 @@ def find_resource(resource, path): raise KeyError('%r has no subelement %s' % (context, view_name)) return context -find_model = find_resource # b/w compat (forever) + +find_model = find_resource # b/w compat (forever) + def find_interface(resource, class_or_interface): """ @@ -121,6 +125,7 @@ def find_interface(resource, class_or_interface): if test(location): return location + def resource_path(resource, *elements): """ Return a string object representing the absolute physical path of the resource object based on its position in the resource tree, e.g @@ -166,7 +171,9 @@ def resource_path(resource, *elements): # which caches the joined result for us return _join_path_tuple(resource_path_tuple(resource, *elements)) -model_path = resource_path # b/w compat (forever) + +model_path = resource_path # b/w compat (forever) + def traverse(resource, path): """Given a resource object as ``resource`` and a string or tuple @@ -314,7 +321,8 @@ def traverse(resource, path): request_factory = reg.queryUtility(IRequestFactory) if request_factory is None: - from pyramid.request import Request # avoid circdep + from pyramid.request import Request # avoid circdep + request_factory = Request request = request_factory.blank(path) @@ -325,6 +333,7 @@ def traverse(resource, path): return traverser(request) + def resource_path_tuple(resource, *elements): """ Return a tuple representing the absolute physical path of the @@ -365,8 +374,10 @@ def resource_path_tuple(resource, *elements): """ return tuple(_resource_path_list(resource, *elements)) + model_path_tuple = resource_path_tuple # b/w compat (forever) + def _resource_path_list(resource, *elements): """ Implementation detail shared by resource_path and resource_path_tuple""" path = [loc.__name__ or '' for loc in lineage(resource)] @@ -374,7 +385,9 @@ def _resource_path_list(resource, *elements): path.extend(elements) return path -_model_path_list = _resource_path_list # b/w compat, not an API + +_model_path_list = _resource_path_list # b/w compat, not an API + def virtual_root(resource, request): """ @@ -412,7 +425,7 @@ def virtual_root(resource, request): vpath, rpath = url_adapter.virtual_path, url_adapter.physical_path if rpath != vpath and rpath.endswith(vpath): - vroot_path = rpath[:-len(vpath)] + vroot_path = rpath[: -len(vpath)] return find_resource(resource, vroot_path) try: @@ -420,6 +433,7 @@ def virtual_root(resource, request): except AttributeError: return find_root(resource) + def traversal_path(path): """ Variant of :func:`pyramid.traversal.traversal_path_info` suitable for decoding paths that are URL-encoded. @@ -435,8 +449,9 @@ def traversal_path(path): # must not possess characters outside ascii path = path.encode('ascii') # we unquote this path exactly like a PEP 3333 server would - path = unquote_bytes_to_wsgi(path) # result will be a native string - return traversal_path_info(path) # result will be a tuple of unicode + path = unquote_bytes_to_wsgi(path) # result will be a native string + return traversal_path_info(path) # result will be a tuple of unicode + @lru_cache(1000) def traversal_path_info(path): @@ -510,10 +525,11 @@ def traversal_path_info(path): applications in :app:`Pyramid`. """ try: - path = decode_path_info(path) # result will be Unicode + path = decode_path_info(path) # result will be Unicode except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) - return split_path_info(path) # result will be tuple of Unicode + return split_path_info(path) # result will be tuple of Unicode + @lru_cache(1000) def split_path_info(path): @@ -531,6 +547,7 @@ def split_path_info(path): clean.append(segment) return tuple(clean) + _segment_cache = {} quote_path_segment_doc = """ \ @@ -574,7 +591,9 @@ if PY2: try: return _segment_cache[(segment, safe)] except KeyError: - if segment.__class__ is text_type: #isinstance slighly slower (~15%) + if ( + segment.__class__ is text_type + ): # isinstance slighly slower (~15%) result = url_quote(segment.encode('utf-8'), safe) else: result = url_quote(str(segment), safe) @@ -582,7 +601,10 @@ if PY2: # 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 @@ -601,8 +623,10 @@ else: _segment_cache[(segment, safe)] = result return result + slash = text_('/') + @implementer(ITraverser) class ResourceTreeTraverser(object): """ A resource tree traverser that should be used (for speed) when @@ -610,7 +634,6 @@ class ResourceTreeTraverser(object): ``__parent__`` attribute (ie. every resource in the tree is :term:`location` aware) .""" - VH_ROOT_KEY = VH_ROOT_KEY VIEW_SELECTOR = '@@' @@ -647,14 +670,17 @@ class ResourceTreeTraverser(object): # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as e: - raise URLDecodeError(e.encoding, e.object, e.start, e.end, - e.reason) + raise URLDecodeError( + e.encoding, e.object, e.start, e.end, e.reason + ) if self.VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[self.VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) - vpath = vroot_path + path # both will (must) be unicode or asciistr + vpath = ( + vroot_path + path + ) # both will (must) be unicode or asciistr vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () @@ -664,7 +690,7 @@ class ResourceTreeTraverser(object): root = self.root ob = vroot = root - if vpath == slash: # invariant: vpath must not be empty + if vpath == slash: # 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 = () @@ -677,44 +703,60 @@ class ResourceTreeTraverser(object): vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: - return {'context': ob, - 'view_name': segment[2:], - 'subpath': vpath_tuple[i + 1:], - 'traversed': vpath_tuple[:vroot_idx + i + 1], - 'virtual_root': vroot, - 'virtual_root_path': vroot_tuple, - 'root': root} + return { + 'context': ob, + 'view_name': segment[2:], + 'subpath': vpath_tuple[i + 1 :], + 'traversed': vpath_tuple[: vroot_idx + i + 1], + 'virtual_root': vroot, + 'virtual_root_path': vroot_tuple, + 'root': root, + } try: getitem = ob.__getitem__ except AttributeError: - return {'context': ob, - 'view_name': segment, - 'subpath': vpath_tuple[i + 1:], - 'traversed': vpath_tuple[:vroot_idx + i + 1], - 'virtual_root': vroot, - 'virtual_root_path': vroot_tuple, - 'root': root} + return { + 'context': ob, + 'view_name': segment, + 'subpath': vpath_tuple[i + 1 :], + 'traversed': vpath_tuple[: vroot_idx + i + 1], + 'virtual_root': vroot, + 'virtual_root_path': vroot_tuple, + 'root': root, + } try: next = getitem(segment) except KeyError: - return {'context': ob, - 'view_name': segment, - 'subpath': vpath_tuple[i + 1:], - 'traversed': vpath_tuple[:vroot_idx + i + 1], - 'virtual_root': vroot, - 'virtual_root_path': vroot_tuple, - 'root': root} + return { + 'context': ob, + 'view_name': segment, + 'subpath': vpath_tuple[i + 1 :], + 'traversed': vpath_tuple[: vroot_idx + i + 1], + 'virtual_root': vroot, + 'virtual_root_path': vroot_tuple, + 'root': root, + } if i == vroot_idx: vroot = next ob = next i += 1 - return {'context':ob, 'view_name':empty, 'subpath':subpath, - 'traversed':vpath_tuple, 'virtual_root':vroot, - 'virtual_root_path':vroot_tuple, 'root':root} + return { + 'context': ob, + 'view_name': empty, + 'subpath': subpath, + 'traversed': vpath_tuple, + 'virtual_root': vroot, + 'virtual_root_path': vroot_tuple, + 'root': root, + } + + +ModelGraphTraverser = ( + ResourceTreeTraverser +) # b/w compat, not API, used in wild -ModelGraphTraverser = ResourceTreeTraverser # b/w compat, not API, used in wild @implementer(IResourceURL) class ResourceURL(object): @@ -742,19 +784,24 @@ class ResourceURL(object): vroot_path_tuple = tuple(vroot_path.split('/')) numels = len(vroot_path_tuple) virtual_path_tuple = ('',) + physical_path_tuple[numels:] - virtual_path = physical_path[len(vroot_path):] + virtual_path = physical_path[len(vroot_path) :] - self.virtual_path = virtual_path # IResourceURL attr + self.virtual_path = virtual_path # IResourceURL attr self.physical_path = physical_path # IResourceURL attr - self.virtual_path_tuple = virtual_path_tuple # IResourceURL attr (1.5) - self.physical_path_tuple = physical_path_tuple # IResourceURL attr (1.5) + self.virtual_path_tuple = virtual_path_tuple # IResourceURL attr (1.5) + self.physical_path_tuple = ( + physical_path_tuple + ) # IResourceURL attr (1.5) + @lru_cache(1000) def _join_path_tuple(tuple): return tuple and '/'.join([quote_path_segment(x) for x in tuple]) or '/' + class DefaultRootFactory: __parent__ = None __name__ = None + def __init__(self, request): pass diff --git a/src/pyramid/tweens.py b/src/pyramid/tweens.py index 740b6961c..839c53b8f 100644 --- a/src/pyramid/tweens.py +++ b/src/pyramid/tweens.py @@ -3,6 +3,7 @@ import sys from pyramid.compat import reraise from pyramid.httpexceptions import HTTPNotFound + def _error_handler(request, exc): # NOTE: we do not need to delete exc_info because this function # should never be in the call stack of the exception @@ -17,6 +18,7 @@ def _error_handler(request, exc): return response + def excview_tween_factory(handler, registry): """ A :term:`tween` factory which produces a tween that catches an exception raised by downstream tweens (or the main Pyramid request @@ -43,6 +45,7 @@ def excview_tween_factory(handler, registry): return excview_tween + MAIN = 'MAIN' INGRESS = 'INGRESS' EXCVIEW = 'pyramid.tweens.excview_tween_factory' diff --git a/src/pyramid/url.py b/src/pyramid/url.py index 852aa5e55..c6cf3da7f 100644 --- a/src/pyramid/url.py +++ b/src/pyramid/url.py @@ -2,21 +2,10 @@ import os -from pyramid.interfaces import ( - IResourceURL, - IRoutesMapper, - IStaticURLInfo, - ) +from pyramid.interfaces import IResourceURL, IRoutesMapper, IStaticURLInfo -from pyramid.compat import ( - bytes_, - lru_cache, - string_types, - ) -from pyramid.encode import ( - url_quote, - urlencode, -) +from pyramid.compat import bytes_, lru_cache, string_types +from pyramid.encode import url_quote, urlencode from pyramid.path import caller_package from pyramid.threadlocal import get_current_registry @@ -25,11 +14,12 @@ from pyramid.traversal import ( quote_path_segment, PATH_SAFE, PATH_SEGMENT_SAFE, - ) +) -QUERY_SAFE = "/?:@!$&'()*+,;=" # RFC 3986 +QUERY_SAFE = "/?:@!$&'()*+,;=" # RFC 3986 ANCHOR_SAFE = QUERY_SAFE + def parse_url_overrides(request, kw): """ Parse special arguments passed when generating urls. @@ -48,7 +38,7 @@ def parse_url_overrides(request, kw): anchor = kw.pop('_anchor', '') if app_url is None: - if (scheme is not None or host is not None or port is not None): + if scheme is not None or host is not None or port is not None: app_url = request._partial_application_url(scheme, host, port) else: app_url = request.application_url @@ -66,6 +56,7 @@ def parse_url_overrides(request, kw): return app_url, qs, frag + class URLMethodsMixin(object): """ Request methods mixin for BaseRequest having to do with URL generation """ @@ -115,7 +106,7 @@ class URLMethodsMixin(object): if port: url += ':%s' % port - url_encoding = getattr(self, 'url_encoding', 'utf-8') # webob 1.2b3+ + url_encoding = getattr(self, 'url_encoding', 'utf-8') # webob 1.2b3+ bscript_name = bytes_(self.script_name, url_encoding) return url + url_quote(bscript_name, PATH_SAFE) @@ -255,7 +246,7 @@ class URLMethodsMixin(object): try: reg = self.registry except AttributeError: - reg = get_current_registry() # b/c + reg = get_current_registry() # b/c mapper = reg.getUtility(IRoutesMapper) route = mapper.get_route(route_name) @@ -267,7 +258,7 @@ class URLMethodsMixin(object): app_url, qs, anchor = parse_url_overrides(self, kw) - path = route.generate(kw) # raises KeyError if generate fails + path = route.generate(kw) # raises KeyError if generate fails if elements: suffix = _join_elements(elements) @@ -522,7 +513,7 @@ class URLMethodsMixin(object): try: reg = self.registry except AttributeError: - reg = get_current_registry() # b/c + reg = get_current_registry() # b/c url_adapter = reg.queryMultiAdapter((resource, self), IResourceURL) if url_adapter is None: @@ -531,9 +522,7 @@ class URLMethodsMixin(object): virtual_path = getattr(url_adapter, 'virtual_path', None) urlkw = {} - for name in ( - 'app_url', 'scheme', 'host', 'port', 'query', 'anchor' - ): + for name in ('app_url', 'scheme', 'host', 'port', 'query', 'anchor'): val = kw.get(name, None) if val is not None: urlkw['_' + name] = val @@ -583,7 +572,7 @@ class URLMethodsMixin(object): return resource_url + suffix + qs + anchor - model_url = resource_url # b/w compat forever + model_url = resource_url # b/w compat forever def resource_path(self, resource, *elements, **kw): """ @@ -651,7 +640,7 @@ class URLMethodsMixin(object): try: reg = self.registry except AttributeError: - reg = get_current_registry() # b/c + reg = get_current_registry() # b/c info = reg.queryUtility(IStaticURLInfo) if info is None: @@ -803,6 +792,7 @@ def route_url(route_name, request, *elements, **kw): """ return request.route_url(route_name, *elements, **kw) + def route_path(route_name, request, *elements, **kw): """ This is a backwards compatibility function. Its result is the same as @@ -814,6 +804,7 @@ def route_path(route_name, request, *elements, **kw): """ return request.route_path(route_name, *elements, **kw) + def resource_url(resource, request, *elements, **kw): """ This is a backwards compatibility function. Its result is the same as @@ -825,7 +816,8 @@ def resource_url(resource, request, *elements, **kw): """ return request.resource_url(resource, *elements, **kw) -model_url = resource_url # b/w compat (forever) + +model_url = resource_url # b/w compat (forever) def static_url(path, request, **kw): @@ -865,6 +857,7 @@ def static_path(path, request, **kw): path = '%s:%s' % (package.__name__, path) return request.static_path(path, **kw) + def current_route_url(request, *elements, **kw): """ This is a backwards compatibility function. Its result is the same as @@ -877,6 +870,7 @@ def current_route_url(request, *elements, **kw): """ return request.current_route_url(*elements, **kw) + def current_route_path(request, *elements, **kw): """ This is a backwards compatibility function. Its result is the same as @@ -889,6 +883,9 @@ def current_route_path(request, *elements, **kw): """ return request.current_route_path(*elements, **kw) + @lru_cache(1000) def _join_elements(elements): - return '/'.join([quote_path_segment(s, safe=PATH_SEGMENT_SAFE) for s in elements]) + return '/'.join( + [quote_path_segment(s, safe=PATH_SEGMENT_SAFE) for s in elements] + ) diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index a61071845..de8a69d2a 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -1,10 +1,7 @@ import re from zope.interface import implementer -from pyramid.interfaces import ( - IRoutesMapper, - IRoute, - ) +from pyramid.interfaces import IRoutesMapper, IRoute from pyramid.compat import ( PY2, @@ -15,30 +12,29 @@ from pyramid.compat import ( binary_type, is_nonstr_iter, decode_path_info, - ) +) from pyramid.exceptions import URLDecodeError -from pyramid.traversal import ( - quote_path_segment, - split_path_info, - PATH_SAFE, - ) +from pyramid.traversal import quote_path_segment, split_path_info, PATH_SAFE _marker = object() + @implementer(IRoute) class Route(object): - def __init__(self, name, pattern, factory=None, predicates=(), - pregenerator=None): + def __init__( + self, name, pattern, factory=None, predicates=(), pregenerator=None + ): self.pattern = pattern - self.path = pattern # indefinite b/w compat, not in interface + self.path = pattern # indefinite b/w compat, not in interface self.match, self.generate = _compile_route(pattern) self.name = name self.factory = factory self.predicates = predicates self.pregenerator = pregenerator + @implementer(IRoutesMapper) class RoutesMapper(object): def __init__(self): @@ -59,8 +55,15 @@ class RoutesMapper(object): def get_route(self, name): return self.routes.get(name) - def connect(self, name, pattern, factory=None, predicates=(), - pregenerator=None, static=False): + def connect( + self, + name, + pattern, + factory=None, + predicates=(), + pregenerator=None, + static=False, + ): if name in self.routes: oldroute = self.routes[name] if oldroute in self.routelist: @@ -86,18 +89,21 @@ class RoutesMapper(object): except KeyError: path = '/' except UnicodeDecodeError as e: - raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) + raise URLDecodeError( + e.encoding, e.object, e.start, e.end, e.reason + ) for route in self.routelist: match = route.match(path) if match is not None: preds = route.predicates - info = {'match':match, 'route':route} + info = {'match': match, 'route': route} if preds and not all((p(info, request) for p in preds)): continue return info - return {'route':None, 'match':None} + return {'route': None, 'match': None} + # stolen from bobo and modified old_route_re = re.compile(r'(\:[_a-zA-Z]\w*)') @@ -109,10 +115,12 @@ star_at_end = re.compile(r'\*(\w*)$') # (\{[a-zA-Z][^\}]*\}) but that choked when supplied with e.g. {foo:\d{4}}. route_re = re.compile(r'(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})') + def update_pattern(matchobj): name = matchobj.group(0) return '{%s}' % name[1:] + def _compile_route(route): # This function really wants to consume Unicode patterns natively, but if # someone passes us a bytestring, we allow it by converting it to Unicode @@ -126,7 +134,8 @@ def _compile_route(route): raise ValueError( 'The pattern value passed to add_route must be ' 'either a Unicode string or a plain string without ' - 'any non-ASCII characters (you provided %r).' % route) + 'any non-ASCII characters (you provided %r).' % route + ) if old_route_re.search(route) and not route_re.search(route): route = old_route_re.sub(update_pattern, route) @@ -145,17 +154,19 @@ def _compile_route(route): pat.reverse() rpat = [] gen = [] - prefix = pat.pop() # invar: always at least one element (route='/'+route) + prefix = pat.pop() # invar: always at least one element (route='/'+route) # We want to generate URL-encoded URLs, so we url-quote the prefix, being # careful not to quote any embedded slashes. We have to replace '%' with # '%%' afterwards, as the strings that go into "gen" are used as string # replacement targets. - gen.append(quote_path_segment(prefix, safe='/').replace('%', '%%')) # native - rpat.append(re.escape(prefix)) # unicode + gen.append( + quote_path_segment(prefix, safe='/').replace('%', '%%') + ) # native + rpat.append(re.escape(prefix)) # unicode while pat: - name = pat.pop() # unicode + name = pat.pop() # unicode name = name[1:-1] if ':' in name: # reg may contain colons as well, @@ -163,12 +174,12 @@ def _compile_route(route): name, reg = name.split(':', 1) else: reg = '[^/]+' - gen.append('%%(%s)s' % native_(name)) # native - name = '(?P<%s>%s)' % (name, reg) # unicode + gen.append('%%(%s)s' % native_(name)) # native + name = '(?P<%s>%s)' % (name, reg) # unicode rpat.append(name) - s = pat.pop() # unicode + s = pat.pop() # unicode if s: - rpat.append(re.escape(s)) # unicode + rpat.append(re.escape(s)) # unicode # We want to generate URL-encoded URLs, so we url-quote this # literal in the pattern, being careful not to quote the embedded # slashes. We have to replace '%' with '%%' afterwards, as the @@ -177,12 +188,13 @@ def _compile_route(route): gen.append(quote_path_segment(s, safe='/').replace('%', '%%')) if remainder: - rpat.append('(?P<%s>.*?)' % remainder) # unicode - gen.append('%%(%s)s' % native_(remainder)) # native + rpat.append('(?P<%s>.*?)' % remainder) # unicode + gen.append('%%(%s)s' % native_(remainder)) # native - pattern = ''.join(rpat) + '$' # unicode + pattern = ''.join(rpat) + '$' # unicode 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 @@ -227,9 +239,7 @@ def _compile_route(route): if k == remainder: # a stararg argument if is_nonstr_iter(v): - v = '/'.join( - [q(x) for x in v] - ) # native + v = '/'.join([q(x) for x in v]) # native else: if v.__class__ not in string_types: v = str(v) @@ -243,7 +253,7 @@ def _compile_route(route): # at this point, the value will be a native string newdict[k] = v - result = gen % newdict # native string result + result = gen % newdict # native string result return result return matcher, generator diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 6655455bf..bebf9e7d3 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -1,5 +1,6 @@ from contextlib import contextmanager import functools + try: # py2.7.7+ and py3.3+ have native comparison support from hmac import compare_digest @@ -8,10 +9,7 @@ except ImportError: # pragma: no cover import inspect import weakref -from pyramid.exceptions import ( - ConfigurationError, - CyclicDependencyError, - ) +from pyramid.exceptions import ConfigurationError, CyclicDependencyError from pyramid.compat import ( getargspec, @@ -22,8 +20,8 @@ from pyramid.compat import ( bytes_, text_, PY2, - native_ - ) + native_, +) from pyramid.path import DottedNameResolver as _DottedNameResolver @@ -31,21 +29,26 @@ _marker = object() class DottedNameResolver(_DottedNameResolver): - def __init__(self, package=None): # default to package = None for bw compat + def __init__( + self, package=None + ): # default to package = None for bw compat _DottedNameResolver.__init__(self, package) + def is_string_or_iterable(v): if isinstance(v, string_types): return True if hasattr(v, '__iter__'): return True + def as_sorted_tuple(val): if not is_nonstr_iter(val): val = (val,) val = tuple(sorted(val)) return val + class InstancePropertyHelper(object): """A helper object for assigning properties and descriptors to instances. It is not normally possible to do this because descriptors must be @@ -56,6 +59,7 @@ class InstancePropertyHelper(object): per-property and then invoking :meth:`.apply` on target objects. """ + def __init__(self): self.properties = {} @@ -81,7 +85,8 @@ class InstancePropertyHelper(object): name = callable.__name__ fn = callable if reify: - import pyramid.decorator # avoid circular import + import pyramid.decorator # avoid circular import + fn = pyramid.decorator.reify(fn) elif not is_property: fn = property(fn) @@ -141,6 +146,7 @@ class InstancePropertyHelper(object): if self.properties: self.apply_properties(target, self.properties) + class InstancePropertyMixin(object): """ Mixin that will allow an instance to add properties at run-time as if they had been defined via @property or @reify @@ -200,7 +206,9 @@ class InstancePropertyMixin(object): 1 """ InstancePropertyHelper.set_property( - self, callable, name=name, reify=reify) + self, callable, name=name, reify=reify + ) + class WeakOrderedSet(object): """ Maintain a set of items. @@ -268,6 +276,7 @@ class WeakOrderedSet(object): oid = self._order[-1] return self._items[oid]() + def strings_differ(string1, string2, compare_digest=compare_digest): """Check whether two strings differ while avoiding timing attacks. @@ -299,6 +308,7 @@ def strings_differ(string1, string2, compare_digest=compare_digest): invalid_bits += a != b return invalid_bits != 0 + def object_description(object): """ Produce a human-consumable text description of ``object``, usually involving a Python dotted name. For example: @@ -345,11 +355,12 @@ def object_description(object): return text_('module %s' % modulename) if inspect.ismethod(object): oself = getattr(object, '__self__', None) - if oself is None: # pragma: no cover + 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 text_( + 'method %s of class %s.%s' + % (object.__name__, modulename, oself.__class__.__name__) + ) if inspect.isclass(object): dottedname = '%s.%s' % (modulename, object.__name__) @@ -359,12 +370,14 @@ def object_description(object): return text_('function %s' % dottedname) return text_('object %s' % str(object)) + def shortrepr(object, closer): r = str(object) if len(r) > 100: r = r[:100] + ' ... %s' % closer return r + class Sentinel(object): def __init__(self, repr): self.repr = repr @@ -372,19 +385,18 @@ class Sentinel(object): def __repr__(self): return self.repr + FIRST = Sentinel('FIRST') LAST = Sentinel('LAST') + class TopologicalSorter(object): """ A utility class which can be used to perform topological sorts against tuple-like data.""" + def __init__( - self, - default_before=LAST, - default_after=None, - first=FIRST, - last=LAST, - ): + self, default_before=LAST, default_after=None, first=FIRST, last=LAST + ): self.names = [] self.req_before = set() self.req_after = set() @@ -414,7 +426,7 @@ class TopologicalSorter(object): self.req_before.remove(name) for u in before: self.order.remove((name, u)) - + def add(self, name, val, after=None, before=None): """ Add a node to the sort input. The ``name`` should be a string or any other hashable object, the ``val`` should be the sortable (doesn't @@ -454,7 +466,6 @@ class TopologicalSorter(object): self.order += [(name, o) for o in before] self.req_before.add(name) - def sorted(self): """ Returns the sort input values in topologically sorted order""" order = [(self.first, self.last)] @@ -469,7 +480,7 @@ class TopologicalSorter(object): def add_node(node): if node not in graph: roots.append(node) - graph[node] = [0] # 0 = number of arcs coming into this node + graph[node] = [0] # 0 = number of arcs coming into this node def add_arc(fromnode, tonode): graph[fromnode].append(tonode) @@ -482,7 +493,7 @@ class TopologicalSorter(object): has_before, has_after = set(), set() for a, b in order: - if a in names and b in names: # deal with missing dependencies + if a in names and b in names: # deal with missing dependencies add_arc(a, b) has_before.add(a) has_after.add(b) @@ -507,7 +518,7 @@ class TopologicalSorter(object): for child in children: arcs = graph[child][0] arcs -= 1 - graph[child][0] = arcs + graph[child][0] = arcs if arcs == 0: roots.insert(0, child) del graph[root] @@ -542,6 +553,7 @@ def get_callable_name(name): ) raise ConfigurationError(msg % name) + @contextmanager def hide_attrs(obj, *attrs): """ @@ -574,9 +586,11 @@ def is_same_domain(host, pattern): return False pattern = pattern.lower() - return (pattern[0] == "." and - (host.endswith(pattern) or host == pattern[1:]) or - pattern == host) + return ( + pattern[0] == "." + and (host.endswith(pattern) or host == pattern[1:]) + or pattern == host + ) def make_contextmanager(fn): @@ -590,6 +604,7 @@ def make_contextmanager(fn): @functools.wraps(fn) def wrapper(*a, **kw): yield fn(*a, **kw) + return wrapper diff --git a/src/pyramid/view.py b/src/pyramid/view.py index 769328344..c45b976bb 100644 --- a/src/pyramid/view.py +++ b/src/pyramid/view.py @@ -13,31 +13,26 @@ from pyramid.interfaces import ( IViewClassifier, IRequest, IExceptionViewClassifier, - ) +) from pyramid.compat import decode_path_info from pyramid.compat import reraise as reraise_ -from pyramid.exceptions import ( - ConfigurationError, - PredicateMismatch, -) +from pyramid.exceptions import ConfigurationError, PredicateMismatch from pyramid.httpexceptions import ( HTTPNotFound, HTTPTemporaryRedirect, default_exceptionresponse_view, - ) +) -from pyramid.threadlocal import ( - get_current_registry, - manager, - ) +from pyramid.threadlocal import get_current_registry, manager from pyramid.util import hide_attrs _marker = object() + def render_view_to_response(context, request, name='', secure=True): """ Call the :term:`view callable` configured with a :term:`view configuration` that matches the :term:`view name` ``name`` @@ -84,9 +79,9 @@ def render_view_to_response(context, request, name='', secure=True): name, secure=secure, request_iface=request_iface, - ) + ) - return response # NB: might be None + return response # NB: might be None def render_view_to_iterable(context, request, name='', secure=True): @@ -119,6 +114,7 @@ def render_view_to_iterable(context, request, name='', secure=True): return None return response.app_iter + def render_view(context, request, name='', secure=True): """ Call the :term:`view callable` configured with a :term:`view configuration` that matches the :term:`view name` ``name`` @@ -146,6 +142,7 @@ def render_view(context, request, name='', secure=True): return None return b''.join(iterable) + class view_config(object): """ A function, class or method :term:`decorator` which allows a developer to create view registrations nearer to a :term:`view @@ -213,7 +210,9 @@ class view_config(object): because of the limitation of ``venusian.Scanner.scan``. """ - venusian = venusian # for testing injection + + venusian = venusian # for testing injection + def __init__(self, **settings): if 'for_' in settings: if settings.get('context') is None: @@ -229,8 +228,9 @@ class view_config(object): config = context.config.with_package(info.module) config.add_view(view=ob, **settings) - info = self.venusian.attach(wrapped, callback, category=category, - depth=depth + 1) + info = self.venusian.attach( + wrapped, callback, category=category, depth=depth + 1 + ) if info.scope == 'class': # if the decorator was attached to a method in a class, or @@ -239,10 +239,12 @@ class view_config(object): if settings.get('attr') is None: settings['attr'] = wrapped.__name__ - settings['_info'] = info.codeinfo # fbo "action_method" + settings['_info'] = info.codeinfo # fbo "action_method" return wrapped -bfg_view = view_config # bw compat (forever) + +bfg_view = view_config # bw compat (forever) + class view_defaults(view_config): """ A class :term:`decorator` which, when applied to a class, will @@ -257,6 +259,7 @@ class view_defaults(view_config): wrapped.__view_defaults__ = self.__dict__.copy() return wrapped + class AppendSlashNotFoundViewFactory(object): """ There can only be one :term:`Not Found view` in any :app:`Pyramid` application. Even if you use @@ -292,7 +295,10 @@ class AppendSlashNotFoundViewFactory(object): .. deprecated:: 1.3 """ - def __init__(self, notfound_view=None, redirect_class=HTTPTemporaryRedirect): + + def __init__( + self, notfound_view=None, redirect_class=HTTPTemporaryRedirect + ): if notfound_view is None: notfound_view = default_exceptionresponse_view self.notfound_view = notfound_view @@ -309,9 +315,12 @@ class AppendSlashNotFoundViewFactory(object): qs = request.query_string if qs: qs = '?' + qs - return self.redirect_class(location=request.path + '/' + qs) + return self.redirect_class( + location=request.path + '/' + qs + ) return self.notfound_view(context, request) + append_slash_notfound_view = AppendSlashNotFoundViewFactory() append_slash_notfound_view.__doc__ = """\ For behavior like Django's ``APPEND_SLASH=True``, use this view as the @@ -337,6 +346,7 @@ view as the Not Found view:: """ + class notfound_view_config(object): """ .. versionadded:: 1.3 @@ -417,8 +427,9 @@ class notfound_view_config(object): config = context.config.with_package(info.module) config.add_notfound_view(view=ob, **settings) - info = self.venusian.attach(wrapped, callback, category=category, - depth=depth + 1) + info = self.venusian.attach( + wrapped, callback, category=category, depth=depth + 1 + ) if info.scope == 'class': # if the decorator was attached to a method in a class, or @@ -427,9 +438,10 @@ class notfound_view_config(object): if settings.get('attr') is None: settings['attr'] = wrapped.__name__ - settings['_info'] = info.codeinfo # fbo "action_method" + settings['_info'] = info.codeinfo # fbo "action_method" return wrapped + class forbidden_view_config(object): """ .. versionadded:: 1.3 @@ -479,8 +491,9 @@ class forbidden_view_config(object): config = context.config.with_package(info.module) config.add_forbidden_view(view=ob, **settings) - info = self.venusian.attach(wrapped, callback, category=category, - depth=depth + 1) + info = self.venusian.attach( + wrapped, callback, category=category, depth=depth + 1 + ) if info.scope == 'class': # if the decorator was attached to a method in a class, or @@ -489,9 +502,10 @@ class forbidden_view_config(object): if settings.get('attr') is None: settings['attr'] = wrapped.__name__ - settings['_info'] = info.codeinfo # fbo "action_method" + settings['_info'] = info.codeinfo # fbo "action_method" return wrapped + class exception_view_config(object): """ .. versionadded:: 1.8 @@ -526,6 +540,7 @@ class exception_view_config(object): Added the ``_depth`` and ``_category`` arguments. """ + venusian = venusian def __init__(self, *args, **settings): @@ -545,8 +560,9 @@ class exception_view_config(object): config = context.config.with_package(info.module) config.add_exception_view(view=ob, **settings) - info = self.venusian.attach(wrapped, callback, category=category, - depth=depth + 1) + info = self.venusian.attach( + wrapped, callback, category=category, depth=depth + 1 + ) if info.scope == 'class': # if the decorator was attached to a method in a class, or @@ -555,9 +571,10 @@ class exception_view_config(object): if settings.get('attr') is None: settings['attr'] = wrapped.__name__ - settings['_info'] = info.codeinfo # fbo "action_method" + settings['_info'] = info.codeinfo # fbo "action_method" return wrapped + def _find_views( registry, request_iface, @@ -565,7 +582,7 @@ def _find_views( view_name, view_types=None, view_classifier=None, - ): +): if view_types is None: view_types = (IView, ISecuredView, IMultiView) if view_classifier is None: @@ -581,9 +598,7 @@ def _find_views( source_ifaces = (view_classifier, req_type, ctx_type) for view_type in view_types: view_callable = registered( - source_ifaces, - view_type, - name=view_name, + source_ifaces, view_type, name=view_name ) if view_callable is not None: views.append(view_callable) @@ -599,6 +614,7 @@ def _find_views( return views + def _call_view( registry, request, @@ -609,7 +625,7 @@ def _call_view( view_classifier=None, secure=True, request_iface=None, - ): +): if request_iface is None: request_iface = getattr(request, 'request_iface', IRequest) view_callables = _find_views( @@ -619,7 +635,7 @@ def _call_view( view_name, view_types=view_types, view_classifier=view_classifier, - ) + ) pme = None response = None @@ -631,10 +647,8 @@ def _call_view( # the view will have a __call_permissive__ attribute if it's # secured; otherwise it won't. view_callable = getattr( - view_callable, - '__call_permissive__', - view_callable - ) + view_callable, '__call_permissive__', view_callable + ) # if this view is secured, it will raise a Forbidden # appropriately if the executing user does not have the proper @@ -649,15 +663,13 @@ def _call_view( return response + class ViewMethodsMixin(object): """ Request methods mixin for BaseRequest having to do with executing views """ + def invoke_exception_view( - self, - exc_info=None, - request=None, - secure=True, - reraise=False, + self, exc_info=None, request=None, secure=True, reraise=False ): """ Executes an exception view related to the request it's called upon. The arguments it takes are these: @@ -742,7 +754,7 @@ class ViewMethodsMixin(object): view_classifier=IExceptionViewClassifier, secure=secure, request_iface=request_iface.combined, - ) + ) except Exception: if reraise: reraise_(*exc_info) diff --git a/src/pyramid/viewderivers.py b/src/pyramid/viewderivers.py index d914a4752..0b4758554 100644 --- a/src/pyramid/viewderivers.py +++ b/src/pyramid/viewderivers.py @@ -1,15 +1,9 @@ import inspect -from zope.interface import ( - implementer, - provider, - ) +from zope.interface import implementer, provider from pyramid.security import NO_PERMISSION_REQUIRED -from pyramid.csrf import ( - check_csrf_origin, - check_csrf_token, -) +from pyramid.csrf import check_csrf_origin, check_csrf_token from pyramid.response import Response from pyramid.interfaces import ( @@ -21,21 +15,13 @@ from pyramid.interfaces import ( IResponse, IViewMapper, IViewMapperFactory, - ) +) -from pyramid.compat import ( - is_bound_method, - is_unbound_method, - ) +from pyramid.compat import is_bound_method, is_unbound_method -from pyramid.exceptions import ( - ConfigurationError, - ) +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 from pyramid.view import render_view_to_response from pyramid import renderers @@ -47,9 +33,11 @@ def view_description(view): # custom view mappers might not add __text__ return object_description(view) + def requestonly(view, attr=None): return takes_one_arg(view, attr=attr, argname='request') + @implementer(IViewMapper) @provider(IViewMapperFactory) class DefaultViewMapper(object): @@ -58,10 +46,12 @@ class DefaultViewMapper(object): def __call__(self, view): if is_unbound_method(view) and self.attr is None: - raise ConfigurationError(( - 'Unbound method calls are not supported, please set the class ' - 'as your `view` and the method as your `attr`' - )) + raise ConfigurationError( + ( + 'Unbound method calls are not supported, please set the class ' + 'as your `view` and the method as your `attr`' + ) + ) if inspect.isclass(view): view = self.map_class(view) @@ -76,7 +66,9 @@ class DefaultViewMapper(object): else: mapped_view = self.map_class_native(view) mapped_view.__text__ = 'method %s of %s' % ( - self.attr or '__call__', object_description(view)) + self.attr or '__call__', + object_description(view), + ) return mapped_view def map_nonclass(self, view): @@ -98,11 +90,15 @@ class DefaultViewMapper(object): # bound method. if is_bound_method(view): _mapped_view = mapped_view + def mapped_view(context, request): return _mapped_view(context, request) + if self.attr is not None: mapped_view.__text__ = 'attr %s of %s' % ( - self.attr, object_description(view)) + self.attr, + object_description(view), + ) else: mapped_view.__text__ = object_description(view) return mapped_view @@ -110,6 +106,7 @@ class DefaultViewMapper(object): def map_class_requestonly(self, view): # its a class that has an __init__ which only accepts request attr = self.attr + def _class_requestonly_view(context, request): inst = view(request) request.__view__ = inst @@ -118,12 +115,14 @@ class DefaultViewMapper(object): else: response = getattr(inst, attr)() return response + return _class_requestonly_view def map_class_native(self, view): # its a class that has an __init__ which accepts both context and # request attr = self.attr + def _class_view(context, request): inst = view(context, request) request.__view__ = inst @@ -132,18 +131,21 @@ class DefaultViewMapper(object): else: response = getattr(inst, attr)() return response + return _class_view def map_nonclass_requestonly(self, view): # its a function that has a __call__ which accepts only a single # request argument attr = self.attr + def _requestonly_view(context, request): if attr is None: response = view(request) else: response = getattr(view, attr)(request) return response + return _requestonly_view def map_nonclass_attr(self, view): @@ -152,6 +154,7 @@ class DefaultViewMapper(object): def _attr_view(context, request): response = getattr(view, self.attr)(context, request) return response + return _attr_view @@ -159,8 +162,10 @@ def wraps_view(wrapper): def inner(view, info): wrapper_view = wrapper(view, info) return preserve_view_attrs(view, wrapper_view) + return inner + def preserve_view_attrs(view, wrapper): if view is None: return wrapper @@ -185,9 +190,16 @@ def preserve_view_attrs(view, wrapper): # attrs that may not exist on "view", but, if so, must be attached to # "wrapped view" - for attr in ('__permitted__', '__call_permissive__', '__permission__', - '__predicated__', '__predicates__', '__accept__', - '__order__', '__text__'): + for attr in ( + '__permitted__', + '__call_permissive__', + '__permission__', + '__predicated__', + '__predicates__', + '__accept__', + '__order__', + '__text__', + ): try: setattr(wrapper, attr, getattr(view, attr)) except AttributeError: @@ -195,6 +207,7 @@ def preserve_view_attrs(view, wrapper): return wrapper + def mapped_view(view, info): mapper = info.options.get('mapper') if mapper is None: @@ -207,29 +220,37 @@ def mapped_view(view, info): mapped_view = mapper(**info.options)(view) return mapped_view + mapped_view.options = ('mapper', 'attr') + def owrapped_view(view, info): wrapper_viewname = info.options.get('wrapper') viewname = info.options.get('name') if not wrapper_viewname: return view + def _owrapped_view(context, request): response = view(context, request) request.wrapped_response = response request.wrapped_body = response.body request.wrapped_view = view - wrapped_response = render_view_to_response(context, request, - wrapper_viewname) + wrapped_response = render_view_to_response( + context, request, wrapper_viewname + ) if wrapped_response is None: raise ValueError( 'No wrapper view named %r found when executing view ' - 'named %r' % (wrapper_viewname, viewname)) + 'named %r' % (wrapper_viewname, viewname) + ) return wrapped_response + return _owrapped_view + owrapped_view.options = ('name', 'wrapper') + def http_cached_view(view, info): if info.settings.get('prevent_http_cache', False): return view @@ -247,27 +268,33 @@ def http_cached_view(view, info): except ValueError: raise ConfigurationError( 'If http_cache parameter is a tuple or list, it must be ' - 'in the form (seconds, options); not %s' % (seconds,)) + 'in the form (seconds, options); not %s' % (seconds,) + ) def wrapper(context, request): response = view(context, request) - prevent_caching = getattr(response.cache_control, 'prevent_auto', - False) + prevent_caching = getattr( + response.cache_control, 'prevent_auto', False + ) if not prevent_caching: response.cache_expires(seconds, **options) return response return wrapper + http_cached_view.options = ('http_cache',) + def secured_view(view, info): for wrapper in (_secured_view, _authdebug_view): view = wraps_view(wrapper)(view, info) return view + secured_view.options = ('permission',) + def _secured_view(view, info): permission = explicit_val = info.options.get('permission') if permission is None: @@ -287,18 +314,23 @@ def _secured_view(view, info): return view if authn_policy and authz_policy and (permission is not None): + def permitted(context, request): principals = authn_policy.effective_principals(request) return authz_policy.permits(context, principals, permission) + def secured_view(context, request): result = permitted(context, request) if result: return view(context, request) view_name = getattr(view, '__name__', view) msg = getattr( - request, 'authdebug_message', - 'Unauthorized: %s failed permission check' % view_name) + request, + 'authdebug_message', + 'Unauthorized: %s failed permission check' % view_name, + ) raise HTTPForbidden(msg, result=result) + wrapped_view = secured_view wrapped_view.__call_permissive__ = view wrapped_view.__permitted__ = permitted @@ -306,6 +338,7 @@ def _secured_view(view, info): return wrapped_view + def _authdebug_view(view, info): wrapped_view = view settings = info.settings @@ -321,6 +354,7 @@ def _authdebug_view(view, info): return view if settings and settings.get('debug_authorization', False): + def authdebug_view(context, request): view_name = getattr(request, 'view_name', None) @@ -331,24 +365,29 @@ def _authdebug_view(view, info): msg = 'Allowed (no permission registered)' else: principals = authn_policy.effective_principals(request) - msg = str(authz_policy.permits( - context, principals, permission)) + msg = str( + authz_policy.permits(context, principals, permission) + ) else: msg = 'Allowed (no authorization policy in use)' view_name = getattr(request, 'view_name', None) url = getattr(request, 'url', None) - msg = ('debug_authorization of url %s (view name %r against ' - 'context %r): %s' % (url, view_name, context, msg)) + msg = ( + 'debug_authorization of url %s (view name %r against ' + 'context %r): %s' % (url, view_name, context, msg) + ) if logger: logger.debug(msg) if request is not None: request.authdebug_message = msg return view(context, request) + wrapped_view = authdebug_view return wrapped_view + def rendered_view(view, info): # one way or another this wrapper must produce a Response (unless # the renderer is a NullRendererHelper) @@ -360,23 +399,29 @@ def rendered_view(view, info): # a view registration. def viewresult_to_response(context, request): result = view(context, request) - if result.__class__ is Response: # common case + if result.__class__ is Response: # common case response = result else: response = info.registry.queryAdapterOrSelf(result, IResponse) if response is None: if result is None: - append = (' You may have forgotten to return a value ' - 'from the view callable.') + append = ( + ' You may have forgotten to return a value ' + 'from the view callable.' + ) elif isinstance(result, dict): - append = (' You may have forgotten to define a ' - 'renderer in the view configuration.') + append = ( + ' You may have forgotten to define a ' + 'renderer in the view configuration.' + ) else: append = '' - msg = ('Could not convert return value of the view ' - 'callable %s into a response object. ' - 'The value returned was %r.' + append) + msg = ( + 'Could not convert return value of the view ' + 'callable %s into a response object. ' + 'The value returned was %r.' + append + ) raise ValueError(msg % (view_description(view), result)) @@ -389,7 +434,7 @@ def rendered_view(view, info): def rendered_view(context, request): result = view(context, request) - if result.__class__ is Response: # potential common case + if result.__class__ is Response: # potential common case response = result else: # this must adapt, it can't do a simple interface check @@ -403,7 +448,8 @@ def rendered_view(view, info): view_renderer = renderers.RendererHelper( name=renderer_name, package=info.package, - registry=info.registry) + registry=info.registry, + ) else: view_renderer = renderer.clone() if '__view__' in attrs: @@ -411,21 +457,26 @@ def rendered_view(view, info): else: view_inst = getattr(view, '__original_view__', view) response = view_renderer.render_view( - request, result, view_inst, context) + request, result, view_inst, context + ) return response return rendered_view + rendered_view.options = ('renderer',) + def decorated_view(view, info): decorator = info.options.get('decorator') if decorator is None: return view return decorator(view) + decorated_view.options = ('decorator',) + def csrf_view(view, info): explicit_val = info.options.get('require_csrf') defaults = info.registry.queryUtility(IDefaultCSRFOptions) @@ -443,29 +494,29 @@ def csrf_view(view, info): callback = defaults.callback enabled = ( - explicit_val is True or + explicit_val is True + or # fallback to the default val if not explicitly enabled # but only if the view is not an exception view - ( - explicit_val is not False and default_val and - not info.exception_only - ) + (explicit_val is not False and default_val and not info.exception_only) ) # disable if both header and token are disabled enabled = enabled and (token or header) wrapped_view = view if enabled: + def csrf_view(context, request): - if ( - request.method not in safe_methods and - (callback is None or callback(request)) + if request.method not in safe_methods and ( + callback is None or callback(request) ): check_csrf_origin(request, raises=True) check_csrf_token(request, token, header, raises=True) return view(context, request) + wrapped_view = csrf_view return wrapped_view + csrf_view.options = ('require_csrf',) VIEW = 'VIEW' diff --git a/src/pyramid/wsgi.py b/src/pyramid/wsgi.py index 1c1bded32..b3f3803e4 100644 --- a/src/pyramid/wsgi.py +++ b/src/pyramid/wsgi.py @@ -1,6 +1,7 @@ from functools import wraps from pyramid.request import call_app_with_subpath_as_path_info + def wsgiapp(wrapped): """ Decorator to turn a WSGI application into a :app:`Pyramid` :term:`view callable`. This decorator differs from the @@ -41,6 +42,7 @@ def wsgiapp(wrapped): return wraps(wrapped)(decorator) return wraps(wrapped, ('__module__', '__doc__'))(decorator) + def wsgiapp2(wrapped): """ Decorator to turn a WSGI application into a :app:`Pyramid` view callable. This decorator differs from the diff --git a/tests/__init__.py b/tests/__init__.py index a62c29f47..944343e82 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,2 @@ - def dummy_extend(*args): """used to test Configurator.extend""" diff --git a/tests/pkgs/ccbugapp/__init__.py b/tests/pkgs/ccbugapp/__init__.py index afe21d4e0..908a36e3e 100644 --- a/tests/pkgs/ccbugapp/__init__.py +++ b/tests/pkgs/ccbugapp/__init__.py @@ -1,16 +1,20 @@ from webob import Response + def rdf_view(request): """ """ return Response('rdf') + def juri_view(request): """ """ return Response('juri') + def includeme(config): config.add_route('rdf', 'licenses/:license_code/:license_version/rdf') - config.add_route('juri', - 'licenses/:license_code/:license_version/:jurisdiction') + config.add_route( + 'juri', 'licenses/:license_code/:license_version/:jurisdiction' + ) config.add_view(rdf_view, route_name='rdf') config.add_view(juri_view, route_name='juri') diff --git a/tests/pkgs/conflictapp/__init__.py b/tests/pkgs/conflictapp/__init__.py index d85aa0e1e..840813994 100644 --- a/tests/pkgs/conflictapp/__init__.py +++ b/tests/pkgs/conflictapp/__init__.py @@ -2,15 +2,19 @@ from pyramid.response import Response from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy + def aview(request): return Response('a view') + def routeview(request): return Response('route view') + def protectedview(request): return Response('protected view') + def includeme(config): # purposely sorta-randomly ordered (route comes after view naming it, # authz comes after views) @@ -18,7 +22,8 @@ def includeme(config): config.add_view(protectedview, name='protected', permission='view') config.add_view(routeview, route_name='aroute') config.add_route('aroute', '/route') - config.set_authentication_policy(AuthTktAuthenticationPolicy( - 'seekri1t', hashalg='sha512')) + config.set_authentication_policy( + AuthTktAuthenticationPolicy('seekri1t', hashalg='sha512') + ) config.set_authorization_policy(ACLAuthorizationPolicy()) config.include('tests.pkgs.conflictapp.included') diff --git a/tests/pkgs/conflictapp/included.py b/tests/pkgs/conflictapp/included.py index 0b76fb2bc..5f483ff81 100644 --- a/tests/pkgs/conflictapp/included.py +++ b/tests/pkgs/conflictapp/included.py @@ -1,6 +1,9 @@ from webob import Response -def bview(request): return Response('b view') + +def bview(request): + return Response('b view') + def includeme(config): config.add_view(bview) diff --git a/tests/pkgs/defpermbugapp/__init__.py b/tests/pkgs/defpermbugapp/__init__.py index 3e59aa623..81897e86a 100644 --- a/tests/pkgs/defpermbugapp/__init__.py +++ b/tests/pkgs/defpermbugapp/__init__.py @@ -2,25 +2,29 @@ from webob import Response from pyramid.security import NO_PERMISSION_REQUIRED from pyramid.view import view_config + @view_config(name='x') -def x_view(request): # pragma: no cover - return Response('this is private!') +def x_view(request): # pragma: no cover + return Response('this is private!') + @view_config(name='y', permission='private2') -def y_view(request): # pragma: no cover - return Response('this is private too!') - +def y_view(request): # pragma: no cover + return Response('this is private too!') + + @view_config(name='z', permission=NO_PERMISSION_REQUIRED) def z_view(request): - return Response('this is public') + return Response('this is public') + def includeme(config): - from pyramid.authorization import ACLAuthorizationPolicy - from pyramid.authentication import AuthTktAuthenticationPolicy - authn_policy = AuthTktAuthenticationPolicy('seekt1t', hashalg='sha512') - authz_policy = ACLAuthorizationPolicy() - config.scan('tests.pkgs.defpermbugapp') - config._set_authentication_policy(authn_policy) - config._set_authorization_policy(authz_policy) - config.set_default_permission('private') - + from pyramid.authorization import ACLAuthorizationPolicy + from pyramid.authentication import AuthTktAuthenticationPolicy + + authn_policy = AuthTktAuthenticationPolicy('seekt1t', hashalg='sha512') + authz_policy = ACLAuthorizationPolicy() + config.scan('tests.pkgs.defpermbugapp') + config._set_authentication_policy(authn_policy) + config._set_authorization_policy(authz_policy) + config.set_default_permission('private') diff --git a/tests/pkgs/eventonly/__init__.py b/tests/pkgs/eventonly/__init__.py index 452ae35a7..c48b539a1 100644 --- a/tests/pkgs/eventonly/__init__.py +++ b/tests/pkgs/eventonly/__init__.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.events import subscriber + class Yup(object): def __init__(self, val, config): self.val = val @@ -13,37 +14,46 @@ class Yup(object): def __call__(self, event): return getattr(event.response, 'yup', False) + class Foo(object): def __init__(self, response): self.response = response + class Bar(object): pass + @subscriber(Foo) def foo(event): event.response.text += 'foo ' + @subscriber(Foo, yup=True) def fooyup(event): event.response.text += 'fooyup ' - + + @subscriber([Foo, Bar]) def foobar(event): event.response.text += 'foobar ' + @subscriber([Foo, Bar]) def foobar2(event, context): event.response.text += 'foobar2 ' + @subscriber([Foo, Bar], yup=True) def foobaryup(event): event.response.text += 'foobaryup ' + @subscriber([Foo, Bar], yup=True) def foobaryup2(event, context): event.response.text += 'foobaryup2 ' + @view_config(name='sendfoo') def sendfoo(request): response = request.response @@ -51,6 +61,7 @@ def sendfoo(request): request.registry.notify(Foo(response)) return response + @view_config(name='sendfoobar') def sendfoobar(request): response = request.response @@ -58,7 +69,7 @@ def sendfoobar(request): request.registry.notify(Foo(response), Bar()) return response + def includeme(config): config.add_subscriber_predicate('yup', Yup) config.scan('tests.pkgs.eventonly') - diff --git a/tests/pkgs/exceptionviewapp/__init__.py b/tests/pkgs/exceptionviewapp/__init__.py index ffc1b47c6..19804d242 100644 --- a/tests/pkgs/exceptionviewapp/__init__.py +++ b/tests/pkgs/exceptionviewapp/__init__.py @@ -1,31 +1,47 @@ from pyramid.httpexceptions import HTTPException + def includeme(config): config.add_route('route_raise_exception', 'route_raise_exception') config.add_route('route_raise_httpexception', 'route_raise_httpexception') - config.add_route('route_raise_exception2', 'route_raise_exception2', - factory='.models.route_factory') - config.add_route('route_raise_exception3', 'route_raise_exception3', - factory='.models.route_factory2') + config.add_route( + 'route_raise_exception2', + 'route_raise_exception2', + factory='.models.route_factory', + ) + config.add_route( + 'route_raise_exception3', + 'route_raise_exception3', + factory='.models.route_factory2', + ) config.add_route('route_raise_exception4', 'route_raise_exception4') config.add_view('.views.maybe') config.add_view('.views.no', context='.models.NotAnException') config.add_view('.views.yes', context=".models.AnException") config.add_view('.views.raise_exception', name='raise_exception') - config.add_view('.views.raise_exception', - route_name='route_raise_exception') - config.add_view('.views.raise_exception', - route_name='route_raise_exception2') - config.add_view('.views.raise_exception', - route_name='route_raise_exception3') - config.add_view('.views.whoa', context='.models.AnException', - route_name='route_raise_exception3') - config.add_view('.views.raise_exception', - route_name='route_raise_exception4') - config.add_view('.views.whoa', context='.models.AnException', - route_name='route_raise_exception4') - config.add_view('.views.raise_httpexception', - route_name='route_raise_httpexception') + config.add_view( + '.views.raise_exception', route_name='route_raise_exception' + ) + config.add_view( + '.views.raise_exception', route_name='route_raise_exception2' + ) + config.add_view( + '.views.raise_exception', route_name='route_raise_exception3' + ) + config.add_view( + '.views.whoa', + context='.models.AnException', + route_name='route_raise_exception3', + ) + config.add_view( + '.views.raise_exception', route_name='route_raise_exception4' + ) + config.add_view( + '.views.whoa', + context='.models.AnException', + route_name='route_raise_exception4', + ) + config.add_view( + '.views.raise_httpexception', route_name='route_raise_httpexception' + ) config.add_view('.views.catch_httpexception', context=HTTPException) - - diff --git a/tests/pkgs/exceptionviewapp/models.py b/tests/pkgs/exceptionviewapp/models.py index fe407badc..25f8e9156 100644 --- a/tests/pkgs/exceptionviewapp/models.py +++ b/tests/pkgs/exceptionviewapp/models.py @@ -1,18 +1,22 @@ - class NotAnException(object): pass + class AnException(Exception): pass + class RouteContext(object): pass + class RouteContext2(object): pass + def route_factory(*arg): return RouteContext() + def route_factory2(*arg): return RouteContext2() diff --git a/tests/pkgs/exceptionviewapp/views.py b/tests/pkgs/exceptionviewapp/views.py index 4953056bc..ca2c4fffb 100644 --- a/tests/pkgs/exceptionviewapp/views.py +++ b/tests/pkgs/exceptionviewapp/views.py @@ -2,23 +2,30 @@ from webob import Response from .models import AnException from pyramid.httpexceptions import HTTPBadRequest + def no(request): return Response('no') + def yes(request): return Response('yes') - + + def maybe(request): return Response('maybe') + def whoa(request): return Response('whoa') + def raise_exception(request): raise AnException() + def raise_httpexception(request): raise HTTPBadRequest + def catch_httpexception(request): return Response('caught') diff --git a/tests/pkgs/fixtureapp/__init__.py b/tests/pkgs/fixtureapp/__init__.py index 27063aae2..ffc8adb4a 100644 --- a/tests/pkgs/fixtureapp/__init__.py +++ b/tests/pkgs/fixtureapp/__init__.py @@ -3,10 +3,12 @@ def includeme(config): config.add_view('.views.exception_view', context=RuntimeError) config.add_view('.views.protected_view', name='protected.html') config.add_view('.views.erroneous_view', name='error.html') - config.add_view('.views.fixture_view', name='dummyskin.html', - request_type='.views.IDummy') + config.add_view( + '.views.fixture_view', + name='dummyskin.html', + request_type='.views.IDummy', + ) from .models import fixture, IFixture + config.registry.registerUtility(fixture, IFixture) config.add_view('.views.fixture_view', name='another.html') - - diff --git a/tests/pkgs/fixtureapp/models.py b/tests/pkgs/fixtureapp/models.py index d80d14bb3..5ad640df9 100644 --- a/tests/pkgs/fixtureapp/models.py +++ b/tests/pkgs/fixtureapp/models.py @@ -1,8 +1,9 @@ from zope.interface import Interface + class IFixture(Interface): pass + def fixture(): """ """ - diff --git a/tests/pkgs/fixtureapp/subpackage/__init__.py b/tests/pkgs/fixtureapp/subpackage/__init__.py index d3173e636..5bb534f79 100644 --- a/tests/pkgs/fixtureapp/subpackage/__init__.py +++ b/tests/pkgs/fixtureapp/subpackage/__init__.py @@ -1 +1 @@ -#package +# package diff --git a/tests/pkgs/fixtureapp/views.py b/tests/pkgs/fixtureapp/views.py index cbfc5a574..78df81c6f 100644 --- a/tests/pkgs/fixtureapp/views.py +++ b/tests/pkgs/fixtureapp/views.py @@ -2,21 +2,26 @@ from zope.interface import Interface from webob import Response from pyramid.httpexceptions import HTTPForbidden + def fixture_view(context, request): """ """ return Response('fixture') + def erroneous_view(context, request): """ """ raise RuntimeError() + def exception_view(context, request): """ """ return Response('supressed') + def protected_view(context, request): """ """ raise HTTPForbidden() + class IDummy(Interface): pass diff --git a/tests/pkgs/forbiddenapp/__init__.py b/tests/pkgs/forbiddenapp/__init__.py index c378126fc..9ebf62a9d 100644 --- a/tests/pkgs/forbiddenapp/__init__.py +++ b/tests/pkgs/forbiddenapp/__init__.py @@ -2,23 +2,27 @@ from webob import Response from pyramid.httpexceptions import HTTPForbidden from pyramid.compat import bytes_ -def x_view(request): # pragma: no cover - return Response('this is private!') + +def x_view(request): # pragma: no cover + return Response('this is private!') + def forbidden_view(context, request): - msg = context.message - result = context.result - message = msg + '\n' + str(result) - resp = HTTPForbidden() - resp.body = bytes_(message) - return resp + msg = context.message + result = context.result + message = msg + '\n' + str(result) + resp = HTTPForbidden() + resp.body = bytes_(message) + return resp + def includeme(config): - from pyramid.authentication import AuthTktAuthenticationPolicy - from pyramid.authorization import ACLAuthorizationPolicy - authn_policy = AuthTktAuthenticationPolicy('seekr1t', hashalg='sha512') - authz_policy = ACLAuthorizationPolicy() - config._set_authentication_policy(authn_policy) - config._set_authorization_policy(authz_policy) - config.add_view(x_view, name='x', permission='private') - config.add_view(forbidden_view, context=HTTPForbidden) + from pyramid.authentication import AuthTktAuthenticationPolicy + from pyramid.authorization import ACLAuthorizationPolicy + + authn_policy = AuthTktAuthenticationPolicy('seekr1t', hashalg='sha512') + authz_policy = ACLAuthorizationPolicy() + config._set_authentication_policy(authn_policy) + config._set_authorization_policy(authz_policy) + config.add_view(x_view, name='x', permission='private') + config.add_view(forbidden_view, context=HTTPForbidden) diff --git a/tests/pkgs/forbiddenview/__init__.py b/tests/pkgs/forbiddenview/__init__.py index 6b4c3c116..4c78d961c 100644 --- a/tests/pkgs/forbiddenview/__init__.py +++ b/tests/pkgs/forbiddenview/__init__.py @@ -3,22 +3,27 @@ from pyramid.response import Response from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy + @forbidden_view_config(route_name='foo') -def foo_forbidden(request): # pragma: no cover +def foo_forbidden(request): # pragma: no cover return Response('foo_forbidden') + @forbidden_view_config() def forbidden(request): return Response('generic_forbidden') + @view_config(route_name='foo') -def foo(request): # pragma: no cover +def foo(request): # pragma: no cover return Response('OK foo') + @view_config(route_name='bar') -def bar(request): # pragma: no cover +def bar(request): # pragma: no cover return Response('OK bar') + def includeme(config): authn_policy = AuthTktAuthenticationPolicy('seekri1', hashalg='sha512') authz_policy = ACLAuthorizationPolicy() @@ -28,4 +33,3 @@ def includeme(config): config.add_route('foo', '/foo') config.add_route('bar', '/bar') config.scan('tests.pkgs.forbiddenview') - diff --git a/tests/pkgs/hybridapp/__init__.py b/tests/pkgs/hybridapp/__init__.py index 1cc2dde83..001e1b882 100644 --- a/tests/pkgs/hybridapp/__init__.py +++ b/tests/pkgs/hybridapp/__init__.py @@ -1,39 +1,46 @@ def includeme(config): - # <!-- we want this view to "win" --> - config.add_route('route', 'abc') - config.add_view('.views.route_view', route_name='route') - # <!-- .. even though this one has a more specific context --> - config.add_view('.views.global_view', - context='pyramid.traversal.DefaultRootFactory') - config.add_view('.views.global2_view', - context='pyramid.traversal.DefaultRootFactory', - name='global2') - config.add_route('route2', 'def') - # <!-- we want this view to win for route2 even though global view with - # context is more specific --> - config.add_view('.views.route2_view', route_name='route2') + # <!-- we want this view to "win" --> + config.add_route('route', 'abc') + config.add_view('.views.route_view', route_name='route') + # <!-- .. even though this one has a more specific context --> + config.add_view( + '.views.global_view', context='pyramid.traversal.DefaultRootFactory' + ) + config.add_view( + '.views.global2_view', + context='pyramid.traversal.DefaultRootFactory', + name='global2', + ) + config.add_route('route2', 'def') + # <!-- we want this view to win for route2 even though global view with + # context is more specific --> + config.add_view('.views.route2_view', route_name='route2') - # <!-- the global view should be found for this route --> - config.add_route('route3', 'ghi', use_global_views=True) - # <!-- the global view should not be found for this route --> - config.add_route('route4', 'jkl') - # <!-- the global view should not be found for this route (/global2) --> - config.add_route('route5', 'mno/*traverse') - # <!-- the global view should be found for this route (/global2) --> - config.add_route('route6', 'pqr/*traverse', use_global_views=True) - config.add_route('route7', 'error') - config.add_view('.views.erroneous_view', route_name='route7') - config.add_route('route8', 'error2') - config.add_view('.views.erroneous_view', route_name='route8') - # <!-- we want this view to "win" for route7 as exception view --> - config.add_view('.views.exception_view', context=RuntimeError) - # <!-- we want this view to "win" for route8 as exception view--> - config.add_view('.views.exception2_view', context=RuntimeError, - route_name='route8') - config.add_route('route9', 'error_sub') - config.add_view('.views.erroneous_sub_view', route_name='route9') - # <!-- we want this view to "win" for route9 as exception view... --> - config.add_view('.views.exception2_view', context='.views.SuperException', - route_name='route9') - # <!-- ...even if we have more context-specialized view for exception --> - config.add_view('.views.exception_view', context='.views.SubException') + # <!-- the global view should be found for this route --> + config.add_route('route3', 'ghi', use_global_views=True) + # <!-- the global view should not be found for this route --> + config.add_route('route4', 'jkl') + # <!-- the global view should not be found for this route (/global2) --> + config.add_route('route5', 'mno/*traverse') + # <!-- the global view should be found for this route (/global2) --> + config.add_route('route6', 'pqr/*traverse', use_global_views=True) + config.add_route('route7', 'error') + config.add_view('.views.erroneous_view', route_name='route7') + config.add_route('route8', 'error2') + config.add_view('.views.erroneous_view', route_name='route8') + # <!-- we want this view to "win" for route7 as exception view --> + config.add_view('.views.exception_view', context=RuntimeError) + # <!-- we want this view to "win" for route8 as exception view--> + config.add_view( + '.views.exception2_view', context=RuntimeError, route_name='route8' + ) + config.add_route('route9', 'error_sub') + config.add_view('.views.erroneous_sub_view', route_name='route9') + # <!-- we want this view to "win" for route9 as exception view... --> + config.add_view( + '.views.exception2_view', + context='.views.SuperException', + route_name='route9', + ) + # <!-- ...even if we have more context-specialized view for exception --> + config.add_view('.views.exception_view', context='.views.SubException') diff --git a/tests/pkgs/hybridapp/views.py b/tests/pkgs/hybridapp/views.py index 135ef8290..695a79531 100644 --- a/tests/pkgs/hybridapp/views.py +++ b/tests/pkgs/hybridapp/views.py @@ -1,39 +1,49 @@ from webob import Response + def route_view(request): """ """ return Response('route') + def global_view(request): """ """ return Response('global') + def global2_view(request): """ """ return Response('global2') + def route2_view(request): """ """ return Response('route2') + def exception_view(request): """ """ return Response('supressed') + def exception2_view(request): """ """ return Response('supressed2') + def erroneous_view(request): """ """ raise RuntimeError() + def erroneous_sub_view(request): """ """ raise SubException() + class SuperException(Exception): """ """ + class SubException(SuperException): """ """ diff --git a/tests/pkgs/includeapp1/root.py b/tests/pkgs/includeapp1/root.py index 986356d81..369ab9f38 100644 --- a/tests/pkgs/includeapp1/root.py +++ b/tests/pkgs/includeapp1/root.py @@ -1,10 +1,11 @@ from pyramid.response import Response + def aview(request): return Response('root') + def configure(config): config.add_view(aview) config.include('tests.pkgs.includeapp1.two.configure') config.commit() - diff --git a/tests/pkgs/includeapp1/three.py b/tests/pkgs/includeapp1/three.py index 973f91d99..b8d881244 100644 --- a/tests/pkgs/includeapp1/three.py +++ b/tests/pkgs/includeapp1/three.py @@ -1,10 +1,11 @@ from pyramid.response import Response + def aview(request): return Response('three') + def configure(config): config.add_view(aview, name='three') - config.include('tests.pkgs.includeapp1.two.configure') # should not cycle - config.add_view(aview) # will be overridden by root when resolved - + config.include('tests.pkgs.includeapp1.two.configure') # should not cycle + config.add_view(aview) # will be overridden by root when resolved diff --git a/tests/pkgs/includeapp1/two.py b/tests/pkgs/includeapp1/two.py index 6b8bb5539..727161c8e 100644 --- a/tests/pkgs/includeapp1/two.py +++ b/tests/pkgs/includeapp1/two.py @@ -1,9 +1,11 @@ from pyramid.response import Response + def aview(request): return Response('two') + def configure(config): config.add_view(aview, name='two') config.include('tests.pkgs.includeapp1.three.configure') - config.add_view(aview) # will be overridden by root when resolved + config.add_view(aview) # will be overridden by root when resolved diff --git a/tests/pkgs/notfoundview/__init__.py b/tests/pkgs/notfoundview/__init__.py index 8ba3ff9ed..f606ec671 100644 --- a/tests/pkgs/notfoundview/__init__.py +++ b/tests/pkgs/notfoundview/__init__.py @@ -1,30 +1,35 @@ from pyramid.view import notfound_view_config, view_config from pyramid.response import Response + @notfound_view_config(route_name='foo', append_slash=True) -def foo_notfound(request): # pragma: no cover +def foo_notfound(request): # pragma: no cover return Response('foo_notfound') + @notfound_view_config(route_name='baz') def baz_notfound(request): return Response('baz_notfound') + @notfound_view_config(append_slash=True) def notfound(request): return Response('generic_notfound') + @view_config(route_name='bar') def bar(request): return Response('OK bar') + @view_config(route_name='foo2') def foo2(request): return Response('OK foo2') + def includeme(config): config.add_route('foo', '/foo') config.add_route('foo2', '/foo/') config.add_route('bar', '/bar/') config.add_route('baz', '/baz') config.scan('tests.pkgs.notfoundview') - diff --git a/tests/pkgs/permbugapp/__init__.py b/tests/pkgs/permbugapp/__init__.py index 4868427a5..aedd405f8 100644 --- a/tests/pkgs/permbugapp/__init__.py +++ b/tests/pkgs/permbugapp/__init__.py @@ -2,21 +2,26 @@ from pyramid.compat import escape from pyramid.security import view_execution_permitted from pyramid.response import Response -def x_view(request): # pragma: no cover - return Response('this is private!') + +def x_view(request): # pragma: no cover + return Response('this is private!') + def test(context, request): # should return false - msg = 'Allow ./x? %s' % repr(view_execution_permitted( - context, request, 'x')) - return Response(escape(msg)) + msg = 'Allow ./x? %s' % repr( + view_execution_permitted(context, request, 'x') + ) + return Response(escape(msg)) + def includeme(config): - from pyramid.authentication import AuthTktAuthenticationPolicy - from pyramid.authorization import ACLAuthorizationPolicy - authn_policy = AuthTktAuthenticationPolicy('seekt1t', hashalg='sha512') - authz_policy = ACLAuthorizationPolicy() - config.set_authentication_policy(authn_policy) - config.set_authorization_policy(authz_policy) - config.add_view(test, name='test') - config.add_view(x_view, name='x', permission='private') + from pyramid.authentication import AuthTktAuthenticationPolicy + from pyramid.authorization import ACLAuthorizationPolicy + + authn_policy = AuthTktAuthenticationPolicy('seekt1t', hashalg='sha512') + authz_policy = ACLAuthorizationPolicy() + config.set_authentication_policy(authn_policy) + config.set_authorization_policy(authz_policy) + config.add_view(test, name='test') + config.add_view(x_view, name='x', permission='private') diff --git a/tests/pkgs/rendererscanapp/__init__.py b/tests/pkgs/rendererscanapp/__init__.py index f3276a063..1fc831e66 100644 --- a/tests/pkgs/rendererscanapp/__init__.py +++ b/tests/pkgs/rendererscanapp/__init__.py @@ -1,9 +1,10 @@ from pyramid.view import view_config + @view_config(name='one', renderer='json') def one(request): - return {'name':'One!'} + return {'name': 'One!'} + def includeme(config): config.scan() - diff --git a/tests/pkgs/rendererscanapp/two/__init__.py b/tests/pkgs/rendererscanapp/two/__init__.py index 6f575dd83..7d3990317 100644 --- a/tests/pkgs/rendererscanapp/two/__init__.py +++ b/tests/pkgs/rendererscanapp/two/__init__.py @@ -1,6 +1,6 @@ from pyramid.view import view_config + @view_config(name='two', renderer='json') def two(request): - return {'nameagain':'Two!'} - + return {'nameagain': 'Two!'} diff --git a/tests/pkgs/restbugapp/__init__.py b/tests/pkgs/restbugapp/__init__.py index 9ad79e32e..ae0a80f01 100644 --- a/tests/pkgs/restbugapp/__init__.py +++ b/tests/pkgs/restbugapp/__init__.py @@ -1,15 +1,19 @@ def includeme(config): - config.add_route('gameactions_pet_get_pets', '/pet', - request_method='GET') - config.add_route('gameactions_pet_care_for_pet', '/pet', - request_method='POST') - config.add_view('.views.PetRESTView', - route_name='gameactions_pet_get_pets', - attr='GET', - permission='view', - renderer='json') - config.add_view('.views.PetRESTView', - route_name='gameactions_pet_care_for_pet', - attr='POST', - permission='view', - renderer='json') + config.add_route('gameactions_pet_get_pets', '/pet', request_method='GET') + config.add_route( + 'gameactions_pet_care_for_pet', '/pet', request_method='POST' + ) + config.add_view( + '.views.PetRESTView', + route_name='gameactions_pet_get_pets', + attr='GET', + permission='view', + renderer='json', + ) + config.add_view( + '.views.PetRESTView', + route_name='gameactions_pet_care_for_pet', + attr='POST', + permission='view', + renderer='json', + ) diff --git a/tests/pkgs/restbugapp/views.py b/tests/pkgs/restbugapp/views.py index 2ace59fa9..161321aed 100644 --- a/tests/pkgs/restbugapp/views.py +++ b/tests/pkgs/restbugapp/views.py @@ -1,15 +1,17 @@ from pyramid.response import Response + class BaseRESTView(object): def __init__(self, context, request): self.context = context self.request = request - + + class PetRESTView(BaseRESTView): """ REST Controller to control action of an avatar """ + def __init__(self, context, request): super(PetRESTView, self).__init__(context, request) def GET(self): return Response('gotten') - diff --git a/tests/pkgs/static_abspath/__init__.py b/tests/pkgs/static_abspath/__init__.py index 812cca467..0c875b96f 100644 --- a/tests/pkgs/static_abspath/__init__.py +++ b/tests/pkgs/static_abspath/__init__.py @@ -1,7 +1,7 @@ import os + def includeme(config): - here = here = os.path.dirname(__file__) + here = here = os.path.dirname(__file__) fixtures = os.path.normpath(os.path.join(here, '..', '..', 'fixtures')) config.add_static_view('/', fixtures) - diff --git a/tests/pkgs/static_assetspec/__init__.py b/tests/pkgs/static_assetspec/__init__.py index dcb438aff..e7d3e9373 100644 --- a/tests/pkgs/static_assetspec/__init__.py +++ b/tests/pkgs/static_assetspec/__init__.py @@ -1,3 +1,2 @@ def includeme(config): config.add_static_view('/', 'tests:fixtures') - diff --git a/tests/pkgs/static_routeprefix/__init__.py b/tests/pkgs/static_routeprefix/__init__.py index 6a3a80712..f64f31292 100644 --- a/tests/pkgs/static_routeprefix/__init__.py +++ b/tests/pkgs/static_routeprefix/__init__.py @@ -2,6 +2,6 @@ def includeme(config): config.add_static_view('/static', 'tests:fixtures') config.include(includeme2, route_prefix='/prefix') + def includeme2(config): config.add_static_view('/static', 'tests:fixtures/static') - diff --git a/tests/pkgs/staticpermapp/__init__.py b/tests/pkgs/staticpermapp/__init__.py index b5038260f..ffc87d39a 100644 --- a/tests/pkgs/staticpermapp/__init__.py +++ b/tests/pkgs/staticpermapp/__init__.py @@ -1,25 +1,32 @@ class RootFactory(object): __acl__ = [('Allow', 'fred', 'view')] + def __init__(self, request): pass + class LocalRootFactory(object): __acl__ = [('Allow', 'bob', 'view')] + def __init__(self, request): pass - + def includeme(config): - from pyramid.authentication import RemoteUserAuthenticationPolicy - from pyramid.authorization import ACLAuthorizationPolicy - authn_policy = RemoteUserAuthenticationPolicy() - authz_policy = ACLAuthorizationPolicy() - config._set_authentication_policy(authn_policy) - config._set_authorization_policy(authz_policy) - config.add_static_view('allowed', 'tests:fixtures/static/') - config.add_static_view('protected', 'tests:fixtures/static/', - permission='view') - config.add_static_view('factory_protected', - 'tests:fixtures/static/', - permission='view', - factory=LocalRootFactory) + from pyramid.authentication import RemoteUserAuthenticationPolicy + from pyramid.authorization import ACLAuthorizationPolicy + + authn_policy = RemoteUserAuthenticationPolicy() + authz_policy = ACLAuthorizationPolicy() + config._set_authentication_policy(authn_policy) + config._set_authorization_policy(authz_policy) + config.add_static_view('allowed', 'tests:fixtures/static/') + config.add_static_view( + 'protected', 'tests:fixtures/static/', permission='view' + ) + config.add_static_view( + 'factory_protected', + 'tests:fixtures/static/', + permission='view', + factory=LocalRootFactory, + ) diff --git a/tests/pkgs/subrequestapp/__init__.py b/tests/pkgs/subrequestapp/__init__.py index e4b1d386a..261af6434 100644 --- a/tests/pkgs/subrequestapp/__init__.py +++ b/tests/pkgs/subrequestapp/__init__.py @@ -1,26 +1,31 @@ from pyramid.config import Configurator from pyramid.request import Request + def view_one(request): subreq = Request.blank('/view_two') response = request.invoke_subrequest(subreq, use_tweens=False) return response + def view_two(request): # check that request.foo is valid for a subrequest return 'This came from view_two, foo=%s' % (request.foo,) + def view_three(request): subreq = Request.blank('/view_four') try: return request.invoke_subrequest(subreq, use_tweens=True) - except: # pragma: no cover + except: # pragma: no cover request.response.body = b'Value error raised' return request.response + def view_four(request): raise ValueError('foo') + def view_five(request): subreq = Request.blank('/view_four') try: @@ -29,11 +34,13 @@ def view_five(request): request.response.body = b'Value error raised' return request.response + def excview(request): request.response.status_int = 500 request.response.body = b'Bad stuff happened' return request.response + def main(): config = Configurator() config.add_route('one', '/view_one') @@ -49,4 +56,3 @@ def main(): config.add_view(view_five, route_name='five') config.add_request_method(lambda r: 'bar', 'foo', property=True) return config - diff --git a/tests/pkgs/viewdecoratorapp/__init__.py b/tests/pkgs/viewdecoratorapp/__init__.py index 099bd29d5..99b7ea9c7 100644 --- a/tests/pkgs/viewdecoratorapp/__init__.py +++ b/tests/pkgs/viewdecoratorapp/__init__.py @@ -1,3 +1,2 @@ def includeme(config): config.scan('tests.pkgs.viewdecoratorapp') - diff --git a/tests/pkgs/viewdecoratorapp/views/views.py b/tests/pkgs/viewdecoratorapp/views/views.py index 18ec78847..6879acd2b 100644 --- a/tests/pkgs/viewdecoratorapp/views/views.py +++ b/tests/pkgs/viewdecoratorapp/views/views.py @@ -1,12 +1,11 @@ from pyramid.view import view_config + @view_config(renderer='json', name='first') def first(request): - return {'result':'OK1'} + return {'result': 'OK1'} -@view_config( - renderer='json', - name='second') -def second(request): - return {'result':'OK2'} +@view_config(renderer='json', name='second') +def second(request): + return {'result': 'OK2'} diff --git a/tests/pkgs/wsgiapp2app/__init__.py b/tests/pkgs/wsgiapp2app/__init__.py index e2024198e..f7452f52c 100644 --- a/tests/pkgs/wsgiapp2app/__init__.py +++ b/tests/pkgs/wsgiapp2app/__init__.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.wsgi import wsgiapp2 + @view_config(name='hello', renderer='string') @wsgiapp2 def hello(environ, start_response): @@ -10,8 +11,10 @@ def hello(environ, start_response): start_response('200 OK', response_headers) return [b'Hello!'] + def main(): from pyramid.config import Configurator + c = Configurator() c.scan() return c diff --git a/tests/test_asset.py b/tests/test_asset.py index cddeb48df..55a3c0336 100644 --- a/tests/test_asset.py +++ b/tests/test_asset.py @@ -3,9 +3,11 @@ import os here = os.path.abspath(os.path.dirname(__file__)) + class Test_resolve_asset_spec(unittest.TestCase): def _callFUT(self, spec, package_name='__main__'): from pyramid.resource import resolve_asset_spec + return resolve_asset_spec(spec, package_name) def test_abspath(self): @@ -19,7 +21,7 @@ class Test_resolve_asset_spec(unittest.TestCase): package_name, filename = self._callFUT(path, pkg) self.assertEqual(package_name, 'tests') self.assertEqual(filename, 'test_asset.py') - + def test_abs_spec(self): pkg = 'tests' path = 'pyramid.nottests:test_asset.py' @@ -36,6 +38,7 @@ class Test_resolve_asset_spec(unittest.TestCase): def test_package_name_is_package_object(self): import tests + pkg = tests path = 'test_asset.py' package_name, filename = self._callFUT(path, pkg) @@ -46,6 +49,7 @@ class Test_resolve_asset_spec(unittest.TestCase): class Test_abspath_from_asset_spec(unittest.TestCase): def _callFUT(self, spec, pname='__main__'): from pyramid.resource import abspath_from_asset_spec + return abspath_from_asset_spec(spec, pname) def test_pname_is_None_before_resolve_asset_spec(self): @@ -60,9 +64,11 @@ class Test_abspath_from_asset_spec(unittest.TestCase): result = self._callFUT('abc', 'tests') self.assertEqual(result, os.path.join(here, 'abc')) + class Test_asset_spec_from_abspath(unittest.TestCase): def _callFUT(self, abspath, package): from pyramid.asset import asset_spec_from_abspath + return asset_spec_from_abspath(abspath, package) def test_package_name_is_main(self): @@ -82,7 +88,7 @@ class Test_asset_spec_from_abspath(unittest.TestCase): result = self._callFUT(here, pkg) self.assertEqual(result, here) + class DummyPackage: def __init__(self, name): self.__name__ = name - diff --git a/tests/test_authentication.py b/tests/test_authentication.py index 4fbc3fe2e..fc3e60587 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -1,14 +1,13 @@ import unittest import warnings from pyramid import testing -from pyramid.compat import ( - text_, - bytes_, - ) +from pyramid.compat import text_, bytes_ + class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): def setUp(self): from pyramid.interfaces import IDebugLogger + self.config = testing.setUp() self.config.registry.registerUtility(self, IDebugLogger) self.messages = [] @@ -21,9 +20,11 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): def _makeOne(self, userid=None, callback=None): from pyramid.authentication import CallbackAuthenticationPolicy + class MyAuthenticationPolicy(CallbackAuthenticationPolicy): def unauthenticated_userid(self, request): return userid + policy = MyAuthenticationPolicy() policy.debug = True policy.callback = callback @@ -38,7 +39,8 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): self.messages[0], 'tests.test_authentication.MyAuthenticationPolicy.' 'authenticated_userid: call to unauthenticated_userid returned ' - 'None; returning None') + 'None; returning None', + ) def test_authenticated_userid_no_callback(self): request = DummyRequest(registry=self.config.registry) @@ -47,14 +49,17 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): self.assertEqual(len(self.messages), 1) self.assertEqual( self.messages[0], - "tests.test_authentication.MyAuthenticationPolicy." + "tests.test_authentication.MyAuthenticationPolicy." "authenticated_userid: there was no groupfinder callback; " - "returning 'fred'") + "returning 'fred'", + ) def test_authenticated_userid_with_callback_fail(self): request = DummyRequest(registry=self.config.registry) + def callback(userid, request): return None + policy = self._makeOne(userid='fred', callback=callback) self.assertEqual(policy.authenticated_userid(request), None) self.assertEqual(len(self.messages), 1) @@ -62,12 +67,15 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): self.messages[0], 'tests.test_authentication.MyAuthenticationPolicy.' 'authenticated_userid: groupfinder callback returned None; ' - 'returning None') + 'returning None', + ) def test_authenticated_userid_with_callback_success(self): request = DummyRequest(registry=self.config.registry) + def callback(userid, request): return [] + policy = self._makeOne(userid='fred', callback=callback) self.assertEqual(policy.authenticated_userid(request), 'fred') self.assertEqual(len(self.messages), 1) @@ -75,7 +83,8 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): self.messages[0], "tests.test_authentication.MyAuthenticationPolicy." "authenticated_userid: groupfinder callback returned []; " - "returning 'fred'") + "returning 'fred'", + ) def test_authenticated_userid_fails_cleaning_as_Authenticated(self): request = DummyRequest(registry=self.config.registry) @@ -87,7 +96,8 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): "tests.test_authentication.MyAuthenticationPolicy." "authenticated_userid: use of userid 'system.Authenticated' is " "disallowed by any built-in Pyramid security policy, returning " - "None") + "None", + ) def test_authenticated_userid_fails_cleaning_as_Everyone(self): request = DummyRequest(registry=self.config.registry) @@ -99,107 +109,127 @@ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): "tests.test_authentication.MyAuthenticationPolicy." "authenticated_userid: use of userid 'system.Everyone' is " "disallowed by any built-in Pyramid security policy, returning " - "None") + "None", + ) def test_effective_principals_no_unauthenticated_userid(self): request = DummyRequest(registry=self.config.registry) policy = self._makeOne() - self.assertEqual(policy.effective_principals(request), - ['system.Everyone']) + self.assertEqual( + policy.effective_principals(request), ['system.Everyone'] + ) self.assertEqual(len(self.messages), 1) self.assertEqual( self.messages[0], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: unauthenticated_userid returned None; " - "returning ['system.Everyone']") + "returning ['system.Everyone']", + ) def test_effective_principals_no_callback(self): request = DummyRequest(registry=self.config.registry) policy = self._makeOne(userid='fred') self.assertEqual( policy.effective_principals(request), - ['system.Everyone', 'system.Authenticated', 'fred']) + ['system.Everyone', 'system.Authenticated', 'fred'], + ) self.assertEqual(len(self.messages), 2) self.assertEqual( self.messages[0], 'tests.test_authentication.MyAuthenticationPolicy.' 'effective_principals: groupfinder callback is None, so groups ' - 'is []') + 'is []', + ) self.assertEqual( self.messages[1], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: returning effective principals: " - "['system.Everyone', 'system.Authenticated', 'fred']") + "['system.Everyone', 'system.Authenticated', 'fred']", + ) def test_effective_principals_with_callback_fail(self): request = DummyRequest(registry=self.config.registry) + def callback(userid, request): return None + policy = self._makeOne(userid='fred', callback=callback) self.assertEqual( - policy.effective_principals(request), ['system.Everyone']) + policy.effective_principals(request), ['system.Everyone'] + ) self.assertEqual(len(self.messages), 2) self.assertEqual( self.messages[0], 'tests.test_authentication.MyAuthenticationPolicy.' 'effective_principals: groupfinder callback returned None as ' - 'groups') + 'groups', + ) self.assertEqual( self.messages[1], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: returning effective principals: " - "['system.Everyone']") + "['system.Everyone']", + ) def test_effective_principals_with_callback_success(self): request = DummyRequest(registry=self.config.registry) + def callback(userid, request): return [] + policy = self._makeOne(userid='fred', callback=callback) self.assertEqual( policy.effective_principals(request), - ['system.Everyone', 'system.Authenticated', 'fred']) + ['system.Everyone', 'system.Authenticated', 'fred'], + ) self.assertEqual(len(self.messages), 2) self.assertEqual( self.messages[0], 'tests.test_authentication.MyAuthenticationPolicy.' - 'effective_principals: groupfinder callback returned [] as groups') + 'effective_principals: groupfinder callback returned [] as groups', + ) self.assertEqual( self.messages[1], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: returning effective principals: " - "['system.Everyone', 'system.Authenticated', 'fred']") + "['system.Everyone', 'system.Authenticated', 'fred']", + ) def test_effective_principals_with_unclean_principal_Authenticated(self): request = DummyRequest(registry=self.config.registry) policy = self._makeOne(userid='system.Authenticated') self.assertEqual( - policy.effective_principals(request), - ['system.Everyone']) + policy.effective_principals(request), ['system.Everyone'] + ) self.assertEqual(len(self.messages), 1) self.assertEqual( self.messages[0], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: unauthenticated_userid returned disallowed " "'system.Authenticated'; returning ['system.Everyone'] as if it " - "was None") + "was None", + ) def test_effective_principals_with_unclean_principal_Everyone(self): request = DummyRequest(registry=self.config.registry) policy = self._makeOne(userid='system.Everyone') self.assertEqual( - policy.effective_principals(request), - ['system.Everyone']) + policy.effective_principals(request), ['system.Everyone'] + ) self.assertEqual(len(self.messages), 1) self.assertEqual( self.messages[0], "tests.test_authentication.MyAuthenticationPolicy." "effective_principals: unauthenticated_userid returned disallowed " "'system.Everyone'; returning ['system.Everyone'] as if it " - "was None") + "was None", + ) + class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import RepozeWho1AuthenticationPolicy + return RepozeWho1AuthenticationPolicy def _makeOne(self, identifier_name='auth_tkt', callback=None): @@ -208,11 +238,13 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_class_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) def test_instance_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAuthenticationPolicy + verifyObject(IAuthenticationPolicy, self._makeOne()) def test_unauthenticated_userid_returns_None(self): @@ -222,7 +254,8 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_unauthenticated_userid(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred'}}) + {'repoze.who.identity': {'repoze.who.userid': 'fred'}} + ) policy = self._makeOne() self.assertEqual(policy.unauthenticated_userid(request), 'fred') @@ -233,48 +266,61 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_authenticated_userid(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred'}}) + {'repoze.who.identity': {'repoze.who.userid': 'fred'}} + ) policy = self._makeOne() self.assertEqual(policy.authenticated_userid(request), 'fred') def test_authenticated_userid_repoze_who_userid_is_None(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':None}}) + {'repoze.who.identity': {'repoze.who.userid': None}} + ) policy = self._makeOne() self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid_with_callback_returns_None(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred'}}) + {'repoze.who.identity': {'repoze.who.userid': 'fred'}} + ) + def callback(identity, request): return None + policy = self._makeOne(callback=callback) self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid_with_callback_returns_something(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred'}}) + {'repoze.who.identity': {'repoze.who.userid': 'fred'}} + ) + def callback(identity, request): return ['agroup'] + policy = self._makeOne(callback=callback) self.assertEqual(policy.authenticated_userid(request), 'fred') def test_authenticated_userid_unclean_principal_Authenticated(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'system.Authenticated'}} - ) + { + 'repoze.who.identity': { + 'repoze.who.userid': 'system.Authenticated' + } + } + ) policy = self._makeOne() self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid_unclean_principal_Everyone(self): request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'system.Everyone'}} - ) + {'repoze.who.identity': {'repoze.who.userid': 'system.Everyone'}} + ) policy = self._makeOne() self.assertEqual(policy.authenticated_userid(request), None) def test_effective_principals_None(self): from pyramid.security import Everyone + request = DummyRequest({}) policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) @@ -282,56 +328,86 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_effective_principals_userid_only(self): from pyramid.security import Everyone from pyramid.security import Authenticated + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred'}}) + {'repoze.who.identity': {'repoze.who.userid': 'fred'}} + ) policy = self._makeOne() - self.assertEqual(policy.effective_principals(request), - [Everyone, Authenticated, 'fred']) + self.assertEqual( + policy.effective_principals(request), + [Everyone, Authenticated, 'fred'], + ) def test_effective_principals_userid_and_groups(self): from pyramid.security import Everyone from pyramid.security import Authenticated + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred', - 'groups':['quux', 'biz']}}) + { + 'repoze.who.identity': { + 'repoze.who.userid': 'fred', + 'groups': ['quux', 'biz'], + } + } + ) + def callback(identity, request): return identity['groups'] + policy = self._makeOne(callback=callback) - self.assertEqual(policy.effective_principals(request), - [Everyone, Authenticated, 'fred', 'quux', 'biz']) + self.assertEqual( + policy.effective_principals(request), + [Everyone, Authenticated, 'fred', 'quux', 'biz'], + ) def test_effective_principals_userid_callback_returns_None(self): from pyramid.security import Everyone + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'fred', - 'groups':['quux', 'biz']}}) + { + 'repoze.who.identity': { + 'repoze.who.userid': 'fred', + 'groups': ['quux', 'biz'], + } + } + ) + def callback(identity, request): return None + policy = self._makeOne(callback=callback) self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals_repoze_who_userid_is_None(self): from pyramid.security import Everyone + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':None}} - ) + {'repoze.who.identity': {'repoze.who.userid': None}} + ) policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals_repoze_who_userid_is_unclean_Everyone(self): from pyramid.security import Everyone + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'system.Everyone'}} - ) + {'repoze.who.identity': {'repoze.who.userid': 'system.Everyone'}} + ) policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals_repoze_who_userid_is_unclean_Authenticated( - self): + self + ): from pyramid.security import Everyone + request = DummyRequest( - {'repoze.who.identity':{'repoze.who.userid':'system.Authenticated'}} - ) + { + 'repoze.who.identity': { + 'repoze.who.userid': 'system.Authenticated' + } + } + ) policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) @@ -343,20 +419,20 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_remember(self): authtkt = DummyWhoPlugin() - request = DummyRequest( - {'repoze.who.plugins':{'auth_tkt':authtkt}}) + request = DummyRequest({'repoze.who.plugins': {'auth_tkt': authtkt}}) policy = self._makeOne() result = policy.remember(request, 'fred') self.assertEqual(result[0], request.environ) - self.assertEqual(result[1], {'repoze.who.userid':'fred'}) + self.assertEqual(result[1], {'repoze.who.userid': 'fred'}) def test_remember_kwargs(self): authtkt = DummyWhoPlugin() - request = DummyRequest( - {'repoze.who.plugins':{'auth_tkt':authtkt}}) + request = DummyRequest({'repoze.who.plugins': {'auth_tkt': authtkt}}) policy = self._makeOne() result = policy.remember(request, 'fred', max_age=23) - self.assertEqual(result[1], {'repoze.who.userid':'fred', 'max_age': 23}) + self.assertEqual( + result[1], {'repoze.who.userid': 'fred', 'max_age': 23} + ) def test_forget_no_plugins(self): request = DummyRequest({}) @@ -367,17 +443,21 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase): def test_forget(self): authtkt = DummyWhoPlugin() request = DummyRequest( - {'repoze.who.plugins':{'auth_tkt':authtkt}, - 'repoze.who.identity':{'repoze.who.userid':'fred'}, - }) + { + 'repoze.who.plugins': {'auth_tkt': authtkt}, + 'repoze.who.identity': {'repoze.who.userid': 'fred'}, + } + ) policy = self._makeOne() result = policy.forget(request) self.assertEqual(result[0], request.environ) self.assertEqual(result[1], request.environ['repoze.who.identity']) + class TestRemoteUserAuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import RemoteUserAuthenticationPolicy + return RemoteUserAuthenticationPolicy def _makeOne(self, environ_key='REMOTE_USER', callback=None): @@ -386,11 +466,13 @@ class TestRemoteUserAuthenticationPolicy(unittest.TestCase): def test_class_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) def test_instance_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAuthenticationPolicy + verifyObject(IAuthenticationPolicy, self._makeOne()) def test_unauthenticated_userid_returns_None(self): @@ -399,7 +481,7 @@ class TestRemoteUserAuthenticationPolicy(unittest.TestCase): self.assertEqual(policy.unauthenticated_userid(request), None) def test_unauthenticated_userid(self): - request = DummyRequest({'REMOTE_USER':'fred'}) + request = DummyRequest({'REMOTE_USER': 'fred'}) policy = self._makeOne() self.assertEqual(policy.unauthenticated_userid(request), 'fred') @@ -409,12 +491,13 @@ class TestRemoteUserAuthenticationPolicy(unittest.TestCase): self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid(self): - request = DummyRequest({'REMOTE_USER':'fred'}) + request = DummyRequest({'REMOTE_USER': 'fred'}) policy = self._makeOne() self.assertEqual(policy.authenticated_userid(request), 'fred') def test_effective_principals_None(self): from pyramid.security import Everyone + request = DummyRequest({}) policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) @@ -422,26 +505,31 @@ class TestRemoteUserAuthenticationPolicy(unittest.TestCase): def test_effective_principals(self): from pyramid.security import Everyone from pyramid.security import Authenticated - request = DummyRequest({'REMOTE_USER':'fred'}) + + request = DummyRequest({'REMOTE_USER': 'fred'}) policy = self._makeOne() - self.assertEqual(policy.effective_principals(request), - [Everyone, Authenticated, 'fred']) + self.assertEqual( + policy.effective_principals(request), + [Everyone, Authenticated, 'fred'], + ) def test_remember(self): - request = DummyRequest({'REMOTE_USER':'fred'}) + request = DummyRequest({'REMOTE_USER': 'fred'}) policy = self._makeOne() result = policy.remember(request, 'fred') self.assertEqual(result, []) def test_forget(self): - request = DummyRequest({'REMOTE_USER':'fred'}) + request = DummyRequest({'REMOTE_USER': 'fred'}) policy = self._makeOne() result = policy.forget(request) self.assertEqual(result, []) + class TestAuthTktAuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import AuthTktAuthenticationPolicy + return AuthTktAuthenticationPolicy def _makeOne(self, callback, cookieidentity, **kw): @@ -460,10 +548,16 @@ class TestAuthTktAuthenticationPolicy(unittest.TestCase): def test_allargs(self): # pass all known args inst = self._getTargetClass()( - 'secret', callback=None, cookie_name=None, secure=False, - include_ip=False, timeout=None, reissue_time=None, - hashalg='sha512', samesite=None, - ) + 'secret', + callback=None, + cookie_name=None, + secure=False, + include_ip=False, + timeout=None, + reissue_time=None, + hashalg='sha512', + samesite=None, + ) self.assertEqual(inst.callback, None) def test_hashalg_override(self): @@ -477,8 +571,8 @@ class TestAuthTktAuthenticationPolicy(unittest.TestCase): self.assertEqual(policy.unauthenticated_userid(request), None) def test_unauthenticated_userid(self): - request = DummyRequest({'REMOTE_USER':'fred'}) - policy = self._makeOne(None, {'userid':'fred'}) + request = DummyRequest({'REMOTE_USER': 'fred'}) + policy = self._makeOne(None, {'userid': 'fred'}) self.assertEqual(policy.unauthenticated_userid(request), 'fred') def test_authenticated_userid_no_cookie_identity(self): @@ -488,41 +582,54 @@ class TestAuthTktAuthenticationPolicy(unittest.TestCase): def test_authenticated_userid_callback_returns_None(self): request = DummyRequest({}) + def callback(userid, request): return None - policy = self._makeOne(callback, {'userid':'fred'}) + + policy = self._makeOne(callback, {'userid': 'fred'}) self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid(self): request = DummyRequest({}) + def callback(userid, request): return True - policy = self._makeOne(callback, {'userid':'fred'}) + + policy = self._makeOne(callback, {'userid': 'fred'}) self.assertEqual(policy.authenticated_userid(request), 'fred') def test_effective_principals_no_cookie_identity(self): from pyramid.security import Everyone + request = DummyRequest({}) policy = self._makeOne(None, None) self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals_callback_returns_None(self): from pyramid.security import Everyone + request = DummyRequest({}) + def callback(userid, request): return None - policy = self._makeOne(callback, {'userid':'fred'}) + + policy = self._makeOne(callback, {'userid': 'fred'}) self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals(self): from pyramid.security import Everyone from pyramid.security import Authenticated + request = DummyRequest({}) + def callback(userid, request): return ['group.foo'] - policy = self._makeOne(callback, {'userid':'fred'}) - self.assertEqual(policy.effective_principals(request), - [Everyone, Authenticated, 'fred', 'group.foo']) + + policy = self._makeOne(callback, {'userid': 'fred'}) + self.assertEqual( + policy.effective_principals(request), + [Everyone, Authenticated, 'fred', 'group.foo'], + ) def test_remember(self): request = DummyRequest({}) @@ -534,7 +641,7 @@ class TestAuthTktAuthenticationPolicy(unittest.TestCase): request = DummyRequest({}) policy = self._makeOne(None, None) result = policy.remember(request, 'fred', a=1, b=2) - self.assertEqual(policy.cookie.kw, {'a':1, 'b':2}) + self.assertEqual(policy.cookie.kw, {'a': 1, 'b': 2}) self.assertEqual(result, []) def test_forget(self): @@ -546,16 +653,20 @@ class TestAuthTktAuthenticationPolicy(unittest.TestCase): def test_class_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) def test_instance_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAuthenticationPolicy + verifyObject(IAuthenticationPolicy, self._makeOne(None, None)) + class TestAuthTktCookieHelper(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import AuthTktCookieHelper + return AuthTktCookieHelper def _makeOne(self, *arg, **kw): @@ -570,7 +681,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): return helper def _makeRequest(self, cookie=None, ipv6=False): - environ = {'wsgi.version': (1,0)} + environ = {'wsgi.version': (1, 0)} if ipv6 is False: environ['REMOTE_ADDR'] = '1.1.1.1' @@ -588,7 +699,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): return D def _parseHeaders(self, headers): - return [ self._parseHeader(header) for header in headers ] + return [self._parseHeader(header) for header in headers] def _parseHeader(self, header): cookie = self._parseCookie(header[1]) @@ -596,18 +707,25 @@ class TestAuthTktCookieHelper(unittest.TestCase): def _parseCookie(self, cookie): from pyramid.compat import SimpleCookie + cookies = SimpleCookie() cookies.load(cookie) return cookies.get('auth_tkt') def test_init_cookie_str_reissue_invalid(self): - self.assertRaises(ValueError, self._makeOne, 'secret', reissue_time='invalid value') + self.assertRaises( + ValueError, self._makeOne, 'secret', reissue_time='invalid value' + ) def test_init_cookie_str_timeout_invalid(self): - self.assertRaises(ValueError, self._makeOne, 'secret', timeout='invalid value') + self.assertRaises( + ValueError, self._makeOne, 'secret', timeout='invalid value' + ) def test_init_cookie_str_max_age_invalid(self): - self.assertRaises(ValueError, self._makeOne, 'secret', max_age='invalid value') + self.assertRaises( + ValueError, self._makeOne, 'secret', max_age='invalid value' + ) def test_identify_nocookie(self): helper = self._makeOne('secret') @@ -635,8 +753,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(helper.auth_tkt.secret, 'secret') environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], '') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_include_ipv6(self): helper = self._makeOne('secret', include_ip=True) @@ -652,8 +770,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(helper.auth_tkt.secret, 'secret') environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], '') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_dont_include_ip(self): helper = self._makeOne('secret', include_ip=False) @@ -669,8 +787,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(helper.auth_tkt.secret, 'secret') environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], '') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_int_useridtype(self): helper = self._makeOne('secret', include_ip=False) @@ -685,8 +803,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result['timestamp'], 0) environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:int') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], 'userid_type:int') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_nonuseridtype_user_data(self): helper = self._makeOne('secret', include_ip=False) @@ -701,8 +819,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result['timestamp'], 0) environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'bogus:int') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], 'bogus:int') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_unknown_useridtype(self): helper = self._makeOne('secret', include_ip=False) @@ -717,11 +835,12 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result['timestamp'], 0) environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:unknown') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], 'userid_type:unknown') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_b64str_useridtype(self): from base64 import b64encode + helper = self._makeOne('secret', include_ip=False) helper.auth_tkt.userid = b64encode(b'encoded').strip() helper.auth_tkt.user_data = 'userid_type:b64str' @@ -734,11 +853,12 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result['timestamp'], 0) environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:b64str') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], 'userid_type:b64str') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_good_cookie_b64unicode_useridtype(self): from base64 import b64encode + helper = self._makeOne('secret', include_ip=False) helper.auth_tkt.userid = b64encode(b'\xc3\xa9ncoded').strip() helper.auth_tkt.user_data = 'userid_type:b64unicode' @@ -751,8 +871,8 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result['timestamp'], 0) environ = request.environ self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) - self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:b64unicode') - self.assertEqual(environ['AUTH_TYPE'],'cookie') + self.assertEqual(environ['REMOTE_USER_DATA'], 'userid_type:b64unicode') + self.assertEqual(environ['AUTH_TYPE'], 'cookie') def test_identify_bad_cookie(self): helper = self._makeOne('secret', include_ip=True) @@ -771,22 +891,24 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_timeout_aged(self): import time + helper = self._makeOne('secret', timeout=10) now = time.time() helper.auth_tkt.timestamp = now - 1 helper.now = now + 10 - helper.auth_tkt.tokens = (text_('a'), ) + helper.auth_tkt.tokens = (text_('a'),) request = self._makeRequest('bogus') result = helper.identify(request) self.assertFalse(result) def test_identify_cookie_reissue(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time=0) now = time.time() helper.auth_tkt.timestamp = now helper.now = now + 1 - helper.auth_tkt.tokens = (text_('a'), ) + helper.auth_tkt.tokens = (text_('a'),) request = self._makeRequest('bogus') result = helper.identify(request) self.assertTrue(result) @@ -798,11 +920,12 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_str_reissue(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time='0') now = time.time() helper.auth_tkt.timestamp = now helper.now = now + 1 - helper.auth_tkt.tokens = (text_('a'), ) + helper.auth_tkt.tokens = (text_('a'),) request = self._makeRequest('bogus') result = helper.identify(request) self.assertTrue(result) @@ -814,6 +937,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_reissue_already_reissued_this_request(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time=0) now = time.time() helper.auth_tkt.timestamp = now @@ -826,6 +950,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_reissue_notyet(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time=10) now = time.time() helper.auth_tkt.timestamp = now @@ -837,6 +962,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_reissue_revoked_by_forget(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time=0) now = time.time() helper.auth_tkt.timestamp = now @@ -854,6 +980,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_reissue_revoked_by_remember(self): import time + helper = self._makeOne('secret', timeout=10, reissue_time=0) now = time.time() helper.auth_tkt.timestamp = now @@ -872,6 +999,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_identify_cookie_reissue_with_tokens_default(self): # see https://github.com/Pylons/pyramid/issues#issue/108 import time + helper = self._makeOne('secret', timeout=10, reissue_time=0) auth_tkt = DummyAuthTktModule(tokens=['']) helper.auth_tkt = auth_tkt @@ -902,13 +1030,15 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/; SameSite=Lax')) + self.assertTrue( + result[1][1].endswith('; Domain=localhost; Path=/; SameSite=Lax') + ) self.assertTrue(result[1][1].startswith('auth_tkt=')) self.assertEqual(result[2][0], 'Set-Cookie') - self.assertTrue(result[2][1].endswith( - '; Domain=.localhost; Path=/; SameSite=Lax')) + self.assertTrue( + result[2][1].endswith('; Domain=.localhost; Path=/; SameSite=Lax') + ) self.assertTrue(result[2][1].startswith('auth_tkt=')) def test_remember_nondefault_samesite(self): @@ -922,13 +1052,19 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/; SameSite=Strict')) + self.assertTrue( + result[1][1].endswith( + '; Domain=localhost; Path=/; SameSite=Strict' + ) + ) self.assertTrue(result[1][1].startswith('auth_tkt=')) self.assertEqual(result[2][0], 'Set-Cookie') - self.assertTrue(result[2][1].endswith( - '; Domain=.localhost; Path=/; SameSite=Strict')) + self.assertTrue( + result[2][1].endswith( + '; Domain=.localhost; Path=/; SameSite=Strict' + ) + ) self.assertTrue(result[2][1].startswith('auth_tkt=')) def test_remember_None_samesite(self): @@ -938,17 +1074,15 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(len(result), 3) self.assertEqual(result[0][0], 'Set-Cookie') - self.assertTrue(result[0][1].endswith('; Path=/')) # no samesite + self.assertTrue(result[0][1].endswith('; Path=/')) # no samesite self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/')) + self.assertTrue(result[1][1].endswith('; Domain=localhost; Path=/')) self.assertTrue(result[1][1].startswith('auth_tkt=')) self.assertEqual(result[2][0], 'Set-Cookie') - self.assertTrue(result[2][1].endswith( - '; Domain=.localhost; Path=/')) + self.assertTrue(result[2][1].endswith('; Domain=.localhost; Path=/')) self.assertTrue(result[2][1].startswith('auth_tkt=')) def test_remember_include_ip(self): @@ -962,35 +1096,45 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/; SameSite=Lax')) + self.assertTrue( + result[1][1].endswith('; Domain=localhost; Path=/; SameSite=Lax') + ) self.assertTrue(result[1][1].startswith('auth_tkt=')) self.assertEqual(result[2][0], 'Set-Cookie') - self.assertTrue(result[2][1].endswith( - '; Domain=.localhost; Path=/; SameSite=Lax')) + self.assertTrue( + result[2][1].endswith('; Domain=.localhost; Path=/; SameSite=Lax') + ) self.assertTrue(result[2][1].startswith('auth_tkt=')) def test_remember_path(self): - helper = self._makeOne('secret', include_ip=True, - path="/cgi-bin/app.cgi/") + helper = self._makeOne( + 'secret', include_ip=True, path="/cgi-bin/app.cgi/" + ) request = self._makeRequest() result = helper.remember(request, 'other') self.assertEqual(len(result), 3) self.assertEqual(result[0][0], 'Set-Cookie') - self.assertTrue(result[0][1].endswith( - '; Path=/cgi-bin/app.cgi/; SameSite=Lax')) + self.assertTrue( + result[0][1].endswith('; Path=/cgi-bin/app.cgi/; SameSite=Lax') + ) self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax')) + self.assertTrue( + result[1][1].endswith( + '; Domain=localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax' + ) + ) self.assertTrue(result[1][1].startswith('auth_tkt=')) self.assertEqual(result[2][0], 'Set-Cookie') - self.assertTrue(result[2][1].endswith( - '; Domain=.localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax')) + self.assertTrue( + result[2][1].endswith( + '; Domain=.localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax' + ) + ) self.assertTrue(result[2][1].startswith('auth_tkt=')) def test_remember_http_only(self): @@ -1040,8 +1184,9 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertTrue(result[0][1].startswith('auth_tkt=')) self.assertEqual(result[1][0], 'Set-Cookie') - self.assertTrue(result[1][1].endswith( - '; Domain=localhost; Path=/; SameSite=Lax')) + self.assertTrue( + result[1][1].endswith('; Domain=localhost; Path=/; SameSite=Lax') + ) self.assertTrue(result[1][1].startswith('auth_tkt=')) def test_remember_parent_domain(self): @@ -1052,8 +1197,11 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(len(result), 1) self.assertEqual(result[0][0], 'Set-Cookie') - self.assertTrue(result[0][1].endswith( - '; Domain=.example.com; Path=/; SameSite=Lax')) + self.assertTrue( + result[0][1].endswith( + '; Domain=.example.com; Path=/; SameSite=Lax' + ) + ) self.assertTrue(result[0][1].startswith('auth_tkt=')) def test_remember_parent_domain_supercedes_wild_domain(self): @@ -1062,8 +1210,11 @@ class TestAuthTktCookieHelper(unittest.TestCase): request.domain = 'www.example.com' result = helper.remember(request, 'other') self.assertEqual(len(result), 1) - self.assertTrue(result[0][1].endswith( - '; Domain=.example.com; Path=/; SameSite=Lax')) + self.assertTrue( + result[0][1].endswith( + '; Domain=.example.com; Path=/; SameSite=Lax' + ) + ) def test_remember_explicit_domain(self): helper = self._makeOne('secret', domain='pyramid.bazinga') @@ -1073,30 +1224,42 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(len(result), 1) self.assertEqual(result[0][0], 'Set-Cookie') - self.assertTrue(result[0][1].endswith( - '; Domain=pyramid.bazinga; Path=/; SameSite=Lax')) + self.assertTrue( + result[0][1].endswith( + '; Domain=pyramid.bazinga; Path=/; SameSite=Lax' + ) + ) self.assertTrue(result[0][1].startswith('auth_tkt=')) def test_remember_domain_supercedes_parent_and_wild_domain(self): - helper = self._makeOne('secret', domain='pyramid.bazinga', - parent_domain=True, wild_domain=True) + helper = self._makeOne( + 'secret', + domain='pyramid.bazinga', + parent_domain=True, + wild_domain=True, + ) request = self._makeRequest() request.domain = 'www.example.com' result = helper.remember(request, 'other') self.assertEqual(len(result), 1) - self.assertTrue(result[0][1].endswith( - '; Domain=pyramid.bazinga; Path=/; SameSite=Lax')) + self.assertTrue( + result[0][1].endswith( + '; Domain=pyramid.bazinga; Path=/; SameSite=Lax' + ) + ) def test_remember_binary_userid(self): import base64 + helper = self._makeOne('secret') request = self._makeRequest() result = helper.remember(request, b'userid') values = self._parseHeaders(result) self.assertEqual(len(result), 3) val = self._cookieValue(values[0]) - self.assertEqual(val['userid'], - text_(base64.b64encode(b'userid').strip())) + self.assertEqual( + val['userid'], text_(base64.b64encode(b'userid').strip()) + ) self.assertEqual(val['user_data'], 'userid_type:b64str') def test_remember_int_userid(self): @@ -1111,6 +1274,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_remember_long_userid(self): from pyramid.compat import long + helper = self._makeOne('secret') request = self._makeRequest() result = helper.remember(request, long(1)) @@ -1122,6 +1286,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_remember_unicode_userid(self): import base64 + helper = self._makeOne('secret') request = self._makeRequest() userid = text_(b'\xc2\xa9', 'utf-8') @@ -1129,8 +1294,9 @@ class TestAuthTktCookieHelper(unittest.TestCase): values = self._parseHeaders(result) self.assertEqual(len(result), 3) val = self._cookieValue(values[0]) - self.assertEqual(val['userid'], - text_(base64.b64encode(userid.encode('utf-8')))) + self.assertEqual( + val['userid'], text_(base64.b64encode(userid.encode('utf-8'))) + ) self.assertEqual(val['user_data'], 'userid_type:b64unicode') def test_remember_insane_userid(self): @@ -1169,7 +1335,13 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_remember_str_max_age_invalid(self): helper = self._makeOne('secret') request = self._makeRequest() - self.assertRaises(ValueError, helper.remember, request, 'userid', max_age='invalid value') + self.assertRaises( + ValueError, + helper.remember, + request, + 'userid', + max_age='invalid value', + ) def test_remember_tokens(self): helper = self._makeOne('secret') @@ -1194,18 +1366,24 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result[0][0], 'Set-Cookie') cookieval = result[0][1] - self.assertTrue('SameSite=Strict' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Strict' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) self.assertEqual(result[1][0], 'Set-Cookie') cookieval = result[1][1] - self.assertTrue('SameSite=Strict' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Strict' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) self.assertEqual(result[2][0], 'Set-Cookie') cookieval = result[2][1] - self.assertTrue('SameSite=Strict' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Strict' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) def test_remember_samesite_default(self): helper = self._makeOne('secret') @@ -1215,18 +1393,24 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result[0][0], 'Set-Cookie') cookieval = result[0][1] - self.assertTrue('SameSite=Lax' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Lax' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) self.assertEqual(result[1][0], 'Set-Cookie') cookieval = result[1][1] - self.assertTrue('SameSite=Lax' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Lax' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) self.assertEqual(result[2][0], 'Set-Cookie') cookieval = result[2][1] - self.assertTrue('SameSite=Lax' in - [x.strip() for x in cookieval.split(';')], cookieval) + self.assertTrue( + 'SameSite=Lax' in [x.strip() for x in cookieval.split(';')], + cookieval, + ) def test_remember_unicode_but_ascii_token(self): helper = self._makeOne('secret') @@ -1240,16 +1424,19 @@ class TestAuthTktCookieHelper(unittest.TestCase): helper = self._makeOne('secret') request = self._makeRequest() la = text_(b'La Pe\xc3\xb1a', 'utf-8') - self.assertRaises(ValueError, helper.remember, request, 'other', - tokens=(la,)) + self.assertRaises( + ValueError, helper.remember, request, 'other', tokens=(la,) + ) def test_remember_invalid_token_format(self): helper = self._makeOne('secret') request = self._makeRequest() - self.assertRaises(ValueError, helper.remember, request, 'other', - tokens=('foo bar',)) - self.assertRaises(ValueError, helper.remember, request, 'other', - tokens=('1bar',)) + self.assertRaises( + ValueError, helper.remember, request, 'other', tokens=('foo bar',) + ) + self.assertRaises( + ValueError, helper.remember, request, 'other', tokens=('1bar',) + ) def test_forget(self): helper = self._makeOne('secret') @@ -1261,26 +1448,28 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual( value, 'auth_tkt=; Max-Age=0; Path=/; ' - 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax' - ) + 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax', + ) name, value = headers[1] self.assertEqual(name, 'Set-Cookie') self.assertEqual( value, 'auth_tkt=; Domain=localhost; Max-Age=0; Path=/; ' - 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax' - ) + 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax', + ) name, value = headers[2] self.assertEqual(name, 'Set-Cookie') self.assertEqual( value, 'auth_tkt=; Domain=.localhost; Max-Age=0; Path=/; ' - 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax' - ) + 'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax', + ) + class TestAuthTicket(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.authentication import AuthTicket + return AuthTicket(*arg, **kw) def test_ctor_with_tokens(self): @@ -1297,37 +1486,53 @@ class TestAuthTicket(unittest.TestCase): self.assertEqual(result, '126fd6224912187ee9ffa80e0b81420c') def test_digest_sha512(self): - ticket = self._makeOne('secret', 'userid', '0.0.0.0', - time=10, hashalg='sha512') + ticket = self._makeOne( + 'secret', 'userid', '0.0.0.0', time=10, hashalg='sha512' + ) result = ticket.digest() - self.assertEqual(result, '74770b2e0d5b1a54c2a466ec567a40f7d7823576aa49'\ - '3c65fc3445e9b44097f4a80410319ef8cb256a2e60b9'\ - 'c2002e48a9e33a3e8ee4379352c04ef96d2cb278') + self.assertEqual( + result, + '74770b2e0d5b1a54c2a466ec567a40f7d7823576aa49' + '3c65fc3445e9b44097f4a80410319ef8cb256a2e60b9' + 'c2002e48a9e33a3e8ee4379352c04ef96d2cb278', + ) def test_cookie_value(self): - ticket = self._makeOne('secret', 'userid', '0.0.0.0', time=10, - tokens=('a', 'b')) + ticket = self._makeOne( + 'secret', 'userid', '0.0.0.0', time=10, tokens=('a', 'b') + ) result = ticket.cookie_value() - self.assertEqual(result, - '66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!') + self.assertEqual( + result, '66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!' + ) def test_ipv4(self): - ticket = self._makeOne('secret', 'userid', '198.51.100.1', - time=10, hashalg='sha256') + ticket = self._makeOne( + 'secret', 'userid', '198.51.100.1', time=10, hashalg='sha256' + ) result = ticket.cookie_value() - self.assertEqual(result, 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b'\ - '798400ecdade8d76c530000000auserid!') + self.assertEqual( + result, + 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b' + '798400ecdade8d76c530000000auserid!', + ) def test_ipv6(self): - ticket = self._makeOne('secret', 'userid', '2001:db8::1', - time=10, hashalg='sha256') + ticket = self._makeOne( + 'secret', 'userid', '2001:db8::1', time=10, hashalg='sha256' + ) result = ticket.cookie_value() - self.assertEqual(result, 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c8'\ - '5becf8760cd7a2fa4910000000auserid!') + self.assertEqual( + result, + 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c8' + '5becf8760cd7a2fa4910000000auserid!', + ) + class TestBadTicket(unittest.TestCase): def _makeOne(self, msg, expected=None): from pyramid.authentication import BadTicket + return BadTicket(msg, expected) def test_it(self): @@ -1335,14 +1540,19 @@ class TestBadTicket(unittest.TestCase): self.assertEqual(exc.expected, True) self.assertTrue(isinstance(exc, Exception)) + class Test_parse_ticket(unittest.TestCase): def _callFUT(self, secret, ticket, ip, hashalg='md5'): from pyramid.authentication import parse_ticket + return parse_ticket(secret, ticket, ip, hashalg) def _assertRaisesBadTicket(self, secret, ticket, ip, hashalg='md5'): from pyramid.authentication import BadTicket - self.assertRaises(BadTicket,self._callFUT, secret, ticket, ip, hashalg) + + self.assertRaises( + BadTicket, self._callFUT, secret, ticket, ip, hashalg + ) def test_bad_timestamp(self): ticket = 'x' * 64 @@ -1362,27 +1572,35 @@ class Test_parse_ticket(unittest.TestCase): self.assertEqual(result, (10, 'userid', ['a', 'b'], '')) def test_correct_with_user_data_sha512(self): - ticket = text_('7d947cdef99bad55f8e3382a8bd089bb9dd0547f7925b7d189adc1' - '160cab0ec0e6888faa41eba641a18522b26f19109f3ffafb769767' - 'ba8a26d02aaeae56599a0000000auserid!a,b!') + ticket = text_( + '7d947cdef99bad55f8e3382a8bd089bb9dd0547f7925b7d189adc1' + '160cab0ec0e6888faa41eba641a18522b26f19109f3ffafb769767' + 'ba8a26d02aaeae56599a0000000auserid!a,b!' + ) result = self._callFUT('secret', ticket, '0.0.0.0', 'sha512') self.assertEqual(result, (10, 'userid', ['a', 'b'], '')) def test_ipv4(self): - ticket = text_('b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b798400ecd' - 'ade8d76c530000000auserid!') + ticket = text_( + 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b798400ecd' + 'ade8d76c530000000auserid!' + ) result = self._callFUT('secret', ticket, '198.51.100.1', 'sha256') self.assertEqual(result, (10, 'userid', [''], '')) def test_ipv6(self): - ticket = text_('d025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c85becf8760' - 'cd7a2fa4910000000auserid!') + ticket = text_( + 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c85becf8760' + 'cd7a2fa4910000000auserid!' + ) result = self._callFUT('secret', ticket, '2001:db8::1', 'sha256') self.assertEqual(result, (10, 'userid', [''], '')) + class TestSessionAuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import SessionAuthenticationPolicy + return SessionAuthenticationPolicy def _makeOne(self, callback=None, prefix=''): @@ -1391,11 +1609,13 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): def test_class_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) def test_instance_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAuthenticationPolicy + verifyObject(IAuthenticationPolicy, self._makeOne()) def test_unauthenticated_userid_returns_None(self): @@ -1404,7 +1624,7 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): self.assertEqual(policy.unauthenticated_userid(request), None) def test_unauthenticated_userid(self): - request = DummyRequest(session={'userid':'fred'}) + request = DummyRequest(session={'userid': 'fred'}) policy = self._makeOne() self.assertEqual(policy.unauthenticated_userid(request), 'fred') @@ -1414,42 +1634,55 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid_callback_returns_None(self): - request = DummyRequest(session={'userid':'fred'}) + request = DummyRequest(session={'userid': 'fred'}) + def callback(userid, request): return None + policy = self._makeOne(callback) self.assertEqual(policy.authenticated_userid(request), None) def test_authenticated_userid(self): - request = DummyRequest(session={'userid':'fred'}) + request = DummyRequest(session={'userid': 'fred'}) + def callback(userid, request): return True + policy = self._makeOne(callback) self.assertEqual(policy.authenticated_userid(request), 'fred') def test_effective_principals_no_identity(self): from pyramid.security import Everyone + request = DummyRequest() policy = self._makeOne() self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals_callback_returns_None(self): from pyramid.security import Everyone - request = DummyRequest(session={'userid':'fred'}) + + request = DummyRequest(session={'userid': 'fred'}) + def callback(userid, request): return None + policy = self._makeOne(callback) self.assertEqual(policy.effective_principals(request), [Everyone]) def test_effective_principals(self): from pyramid.security import Everyone from pyramid.security import Authenticated - request = DummyRequest(session={'userid':'fred'}) + + request = DummyRequest(session={'userid': 'fred'}) + def callback(userid, request): return ['group.foo'] + policy = self._makeOne(callback) - self.assertEqual(policy.effective_principals(request), - [Everyone, Authenticated, 'fred', 'group.foo']) + self.assertEqual( + policy.effective_principals(request), + [Everyone, Authenticated, 'fred', 'group.foo'], + ) def test_remember(self): request = DummyRequest() @@ -1459,7 +1692,7 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): self.assertEqual(result, []) def test_forget(self): - request = DummyRequest(session={'userid':'fred'}) + request = DummyRequest(session={'userid': 'fred'}) policy = self._makeOne() result = policy.forget(request) self.assertEqual(request.session.get('userid'), None) @@ -1472,9 +1705,11 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): self.assertEqual(request.session.get('userid'), None) self.assertEqual(result, []) + class TestBasicAuthAuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import BasicAuthAuthenticationPolicy as cls + return cls def _makeOne(self, check): @@ -1483,13 +1718,16 @@ class TestBasicAuthAuthenticationPolicy(unittest.TestCase): def test_class_implements_IAuthenticationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) def test_unauthenticated_userid(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'Basic %s' % base64.b64encode( - bytes_('chrisr:password')).decode('ascii') + bytes_('chrisr:password') + ).decode('ascii') policy = self._makeOne(None) self.assertEqual(policy.unauthenticated_userid(request), 'chrisr') @@ -1518,45 +1756,65 @@ class TestBasicAuthAuthenticationPolicy(unittest.TestCase): def test_authenticated_userid(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'Basic %s' % base64.b64encode( - bytes_('chrisr:password')).decode('ascii') + bytes_('chrisr:password') + ).decode('ascii') + def check(username, password, request): return [] + policy = self._makeOne(check) self.assertEqual(policy.authenticated_userid(request), 'chrisr') def test_authenticated_userid_utf8(self): import base64 + request = testing.DummyRequest() - inputs = (b'm\xc3\xb6rk\xc3\xb6:' - b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + inputs = ( + b'm\xc3\xb6rk\xc3\xb6:' b'm\xc3\xb6rk\xc3\xb6password' + ).decode('utf-8') request.headers['Authorization'] = 'Basic %s' % ( - base64.b64encode(inputs.encode('utf-8')).decode('latin-1')) + base64.b64encode(inputs.encode('utf-8')).decode('latin-1') + ) + def check(username, password, request): return [] + policy = self._makeOne(check) - self.assertEqual(policy.authenticated_userid(request), - b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8')) + self.assertEqual( + policy.authenticated_userid(request), + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), + ) def test_authenticated_userid_latin1(self): import base64 + request = testing.DummyRequest() - inputs = (b'm\xc3\xb6rk\xc3\xb6:' - b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + inputs = ( + b'm\xc3\xb6rk\xc3\xb6:' b'm\xc3\xb6rk\xc3\xb6password' + ).decode('utf-8') request.headers['Authorization'] = 'Basic %s' % ( - base64.b64encode(inputs.encode('latin-1')).decode('latin-1')) + base64.b64encode(inputs.encode('latin-1')).decode('latin-1') + ) + def check(username, password, request): return [] + policy = self._makeOne(check) - self.assertEqual(policy.authenticated_userid(request), - b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8')) + self.assertEqual( + policy.authenticated_userid(request), + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), + ) def test_unauthenticated_userid_invalid_payload(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'Basic %s' % base64.b64encode( - bytes_('chrisrpassword')).decode('ascii') + bytes_('chrisrpassword') + ).decode('ascii') policy = self._makeOne(None) self.assertEqual(policy.unauthenticated_userid(request), None) @@ -1566,13 +1824,16 @@ class TestBasicAuthAuthenticationPolicy(unittest.TestCase): def test_forget(self): policy = self._makeOne(None) - self.assertEqual(policy.forget(None), [ - ('WWW-Authenticate', 'Basic realm="SomeRealm"')]) + self.assertEqual( + policy.forget(None), + [('WWW-Authenticate', 'Basic realm="SomeRealm"')], + ) class TestExtractHTTPBasicCredentials(unittest.TestCase): def _get_func(self): from pyramid.authentication import extract_http_basic_credentials + return extract_http_basic_credentials def test_no_auth_header(self): @@ -1583,17 +1844,21 @@ class TestExtractHTTPBasicCredentials(unittest.TestCase): def test_invalid_payload(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'Basic %s' % base64.b64encode( - bytes_('chrisrpassword')).decode('ascii') + bytes_('chrisrpassword') + ).decode('ascii') fn = self._get_func() self.assertIsNone(fn(request)) def test_not_a_basic_auth_scheme(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'OtherScheme %s' % base64.b64encode( - bytes_('chrisr:password')).decode('ascii') + bytes_('chrisr:password') + ).decode('ascii') fn = self._get_func() self.assertIsNone(fn(request)) @@ -1605,44 +1870,60 @@ class TestExtractHTTPBasicCredentials(unittest.TestCase): def test_latin1_payload(self): import base64 + request = testing.DummyRequest() - inputs = (b'm\xc3\xb6rk\xc3\xb6:' - b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + inputs = ( + b'm\xc3\xb6rk\xc3\xb6:' b'm\xc3\xb6rk\xc3\xb6password' + ).decode('utf-8') request.headers['Authorization'] = 'Basic %s' % ( - base64.b64encode(inputs.encode('latin-1')).decode('latin-1')) + base64.b64encode(inputs.encode('latin-1')).decode('latin-1') + ) fn = self._get_func() - self.assertEqual(fn(request), ( - b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), - b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8') - )) + self.assertEqual( + fn(request), + ( + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), + b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8'), + ), + ) def test_utf8_payload(self): import base64 + request = testing.DummyRequest() - inputs = (b'm\xc3\xb6rk\xc3\xb6:' - b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + inputs = ( + b'm\xc3\xb6rk\xc3\xb6:' b'm\xc3\xb6rk\xc3\xb6password' + ).decode('utf-8') request.headers['Authorization'] = 'Basic %s' % ( - base64.b64encode(inputs.encode('utf-8')).decode('latin-1')) + base64.b64encode(inputs.encode('utf-8')).decode('latin-1') + ) fn = self._get_func() - self.assertEqual(fn(request), ( - b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), - b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8') - )) + self.assertEqual( + fn(request), + ( + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'), + b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8'), + ), + ) def test_namedtuple_return(self): import base64 + request = testing.DummyRequest() request.headers['Authorization'] = 'Basic %s' % base64.b64encode( - bytes_('chrisr:pass')).decode('ascii') + bytes_('chrisr:pass') + ).decode('ascii') fn = self._get_func() result = fn(request) self.assertEqual(result.username, 'chrisr') self.assertEqual(result.password, 'pass') - + + class DummyContext: pass + class DummyCookies(object): def __init__(self, cookie): self.cookie = cookie @@ -1650,8 +1931,10 @@ class DummyCookies(object): def get(self, name): return self.cookie + class DummyRequest: domain = 'localhost' + def __init__(self, environ=None, session=None, registry=None, cookie=None): self.environ = environ or {} self.session = session or {} @@ -1662,6 +1945,7 @@ class DummyRequest: def add_response_callback(self, callback): self.callbacks.append(callback) + class DummyWhoPlugin: def remember(self, environ, identity): return environ, identity @@ -1669,6 +1953,7 @@ class DummyWhoPlugin: def forget(self, environ, identity): return environ, identity + class DummyCookieHelper: def __init__(self, result): self.result = result @@ -1683,15 +1968,24 @@ class DummyCookieHelper: def forget(self, *arg): return [] + class DummyAuthTktModule(object): - def __init__(self, timestamp=0, userid='userid', tokens=(), user_data='', - parse_raise=False, hashalg="md5"): + def __init__( + self, + timestamp=0, + userid='userid', + tokens=(), + user_data='', + parse_raise=False, + hashalg="md5", + ): self.timestamp = timestamp self.userid = userid self.tokens = tokens self.user_data = user_data self.parse_raise = parse_raise self.hashalg = hashalg + def parse_ticket(secret, value, remote_addr, hashalg): self.secret = secret self.value = value @@ -1699,6 +1993,7 @@ class DummyAuthTktModule(object): if self.parse_raise: raise self.BadTicket() return self.timestamp, self.userid, self.tokens, self.user_data + self.parse_ticket = parse_ticket class AuthTicket(object): @@ -1710,10 +2005,10 @@ class DummyAuthTktModule(object): def cookie_value(self): result = { - 'secret':self.secret, - 'userid':self.userid, - 'remote_addr':self.remote_addr - } + 'secret': self.secret, + 'userid': self.userid, + 'remote_addr': self.remote_addr, + } result.update(self.kw) tokens = result.pop('tokens', None) if tokens is not None: @@ -1724,15 +2019,16 @@ class DummyAuthTktModule(object): for k, v in items: if isinstance(v, bytes): v = text_(v) - new_items.append((k,v)) - result = '/'.join(['%s=%s' % (k, v) for k,v in new_items ]) + new_items.append((k, v)) + result = '/'.join(['%s=%s' % (k, v) for k, v in new_items]) return result + self.AuthTicket = AuthTicket class BadTicket(Exception): pass + class DummyResponse: def __init__(self): self.headerlist = [] - diff --git a/tests/test_authorization.py b/tests/test_authorization.py index 05cd3b4f8..efb84b203 100644 --- a/tests/test_authorization.py +++ b/tests/test_authorization.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import cleanUp + class TestACLAuthorizationPolicy(unittest.TestCase): def setUp(self): cleanUp() @@ -11,6 +12,7 @@ class TestACLAuthorizationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authorization import ACLAuthorizationPolicy + return ACLAuthorizationPolicy def _makeOne(self): @@ -19,18 +21,20 @@ class TestACLAuthorizationPolicy(unittest.TestCase): def test_class_implements_IAuthorizationPolicy(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAuthorizationPolicy + verifyClass(IAuthorizationPolicy, self._getTargetClass()) def test_instance_implements_IAuthorizationPolicy(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAuthorizationPolicy + verifyObject(IAuthorizationPolicy, self._makeOne()) def test_permits_no_acl(self): context = DummyContext() policy = self._makeOne() self.assertEqual(policy.permits(context, [], 'view'), False) - + def test_permits(self): from pyramid.security import Deny from pyramid.security import Allow @@ -38,68 +42,76 @@ class TestACLAuthorizationPolicy(unittest.TestCase): from pyramid.security import Authenticated from pyramid.security import ALL_PERMISSIONS from pyramid.security import DENY_ALL + root = DummyContext() community = DummyContext(__name__='community', __parent__=root) blog = DummyContext(__name__='blog', __parent__=community) - root.__acl__ = [ - (Allow, Authenticated, VIEW), - ] + root.__acl__ = [(Allow, Authenticated, VIEW)] community.__acl__ = [ (Allow, 'fred', ALL_PERMISSIONS), (Allow, 'wilma', VIEW), DENY_ALL, - ] + ] blog.__acl__ = [ (Allow, 'barney', MEMBER_PERMS), (Allow, 'wilma', VIEW), - ] + ] policy = self._makeOne() - result = policy.permits(blog, [Everyone, Authenticated, 'wilma'], - 'view') + result = policy.permits( + blog, [Everyone, Authenticated, 'wilma'], 'view' + ) self.assertEqual(result, True) self.assertEqual(result.context, blog) self.assertEqual(result.ace, (Allow, 'wilma', VIEW)) self.assertEqual(result.acl, blog.__acl__) - result = policy.permits(blog, [Everyone, Authenticated, 'wilma'], - 'delete') + result = policy.permits( + blog, [Everyone, Authenticated, 'wilma'], 'delete' + ) self.assertEqual(result, False) self.assertEqual(result.context, community) self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS)) self.assertEqual(result.acl, community.__acl__) - result = policy.permits(blog, [Everyone, Authenticated, 'fred'], 'view') + result = policy.permits( + blog, [Everyone, Authenticated, 'fred'], 'view' + ) self.assertEqual(result, True) self.assertEqual(result.context, community) self.assertEqual(result.ace, (Allow, 'fred', ALL_PERMISSIONS)) - result = policy.permits(blog, [Everyone, Authenticated, 'fred'], - 'doesntevenexistyet') + result = policy.permits( + blog, [Everyone, Authenticated, 'fred'], 'doesntevenexistyet' + ) self.assertEqual(result, True) self.assertEqual(result.context, community) self.assertEqual(result.ace, (Allow, 'fred', ALL_PERMISSIONS)) self.assertEqual(result.acl, community.__acl__) - result = policy.permits(blog, [Everyone, Authenticated, 'barney'], - 'view') + result = policy.permits( + blog, [Everyone, Authenticated, 'barney'], 'view' + ) self.assertEqual(result, True) self.assertEqual(result.context, blog) self.assertEqual(result.ace, (Allow, 'barney', MEMBER_PERMS)) - result = policy.permits(blog, [Everyone, Authenticated, 'barney'], - 'administer') + result = policy.permits( + blog, [Everyone, Authenticated, 'barney'], 'administer' + ) self.assertEqual(result, False) self.assertEqual(result.context, community) self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS)) self.assertEqual(result.acl, community.__acl__) - - result = policy.permits(root, [Everyone, Authenticated, 'someguy'], - 'view') + + result = policy.permits( + root, [Everyone, Authenticated, 'someguy'], 'view' + ) self.assertEqual(result, True) self.assertEqual(result.context, root) self.assertEqual(result.ace, (Allow, Authenticated, VIEW)) - result = policy.permits(blog, - [Everyone, Authenticated, 'someguy'], 'view') + result = policy.permits( + blog, [Everyone, Authenticated, 'someguy'], 'view' + ) self.assertEqual(result, False) self.assertEqual(result.context, community) self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS)) @@ -116,128 +128,149 @@ class TestACLAuthorizationPolicy(unittest.TestCase): self.assertEqual(result, False) self.assertEqual(result.ace, '<default deny>') self.assertEqual( - result.acl, - '<No ACL found on any object in resource lineage>') + result.acl, '<No ACL found on any object in resource lineage>' + ) def test_permits_string_permissions_in_acl(self): from pyramid.security import Allow + root = DummyContext() - root.__acl__ = [ - (Allow, 'wilma', 'view_stuff'), - ] + root.__acl__ = [(Allow, 'wilma', 'view_stuff')] policy = self._makeOne() result = policy.permits(root, ['wilma'], 'view') # would be True if matching against 'view_stuff' instead of against # ['view_stuff'] - self.assertEqual(result, False) + self.assertEqual(result, False) def test_principals_allowed_by_permission_direct(self): from pyramid.security import Allow from pyramid.security import DENY_ALL + context = DummyContext() - acl = [ (Allow, 'chrism', ('read', 'write')), - DENY_ALL, - (Allow, 'other', 'read') ] + acl = [ + (Allow, 'chrism', ('read', 'write')), + DENY_ALL, + (Allow, 'other', 'read'), + ] context.__acl__ = acl policy = self._makeOne() result = sorted( - policy.principals_allowed_by_permission(context, 'read')) + policy.principals_allowed_by_permission(context, 'read') + ) self.assertEqual(result, ['chrism']) def test_principals_allowed_by_permission_callable_acl(self): from pyramid.security import Allow from pyramid.security import DENY_ALL + context = DummyContext() - acl = lambda: [ (Allow, 'chrism', ('read', 'write')), - DENY_ALL, - (Allow, 'other', 'read') ] + acl = lambda: [ + (Allow, 'chrism', ('read', 'write')), + DENY_ALL, + (Allow, 'other', 'read'), + ] context.__acl__ = acl policy = self._makeOne() result = sorted( - policy.principals_allowed_by_permission(context, 'read')) + policy.principals_allowed_by_permission(context, 'read') + ) self.assertEqual(result, ['chrism']) - + def test_principals_allowed_by_permission_string_permission(self): from pyramid.security import Allow + context = DummyContext() - acl = [ (Allow, 'chrism', 'read_it')] + acl = [(Allow, 'chrism', 'read_it')] context.__acl__ = acl policy = self._makeOne() result = policy.principals_allowed_by_permission(context, 'read') # would be ['chrism'] if 'read' were compared against 'read_it' instead # of against ['read_it'] self.assertEqual(list(result), []) - + def test_principals_allowed_by_permission(self): from pyramid.security import Allow from pyramid.security import Deny from pyramid.security import DENY_ALL from pyramid.security import ALL_PERMISSIONS + root = DummyContext(__name__='', __parent__=None) community = DummyContext(__name__='community', __parent__=root) blog = DummyContext(__name__='blog', __parent__=community) - root.__acl__ = [ (Allow, 'chrism', ('read', 'write')), - (Allow, 'other', ('read',)), - (Allow, 'jim', ALL_PERMISSIONS)] - community.__acl__ = [ (Deny, 'flooz', 'read'), - (Allow, 'flooz', 'read'), - (Allow, 'mork', 'read'), - (Deny, 'jim', 'read'), - (Allow, 'someguy', 'manage')] - blog.__acl__ = [ (Allow, 'fred', 'read'), - DENY_ALL] + root.__acl__ = [ + (Allow, 'chrism', ('read', 'write')), + (Allow, 'other', ('read',)), + (Allow, 'jim', ALL_PERMISSIONS), + ] + community.__acl__ = [ + (Deny, 'flooz', 'read'), + (Allow, 'flooz', 'read'), + (Allow, 'mork', 'read'), + (Deny, 'jim', 'read'), + (Allow, 'someguy', 'manage'), + ] + blog.__acl__ = [(Allow, 'fred', 'read'), DENY_ALL] policy = self._makeOne() - + result = sorted(policy.principals_allowed_by_permission(blog, 'read')) self.assertEqual(result, ['fred']) - result = sorted(policy.principals_allowed_by_permission(community, - 'read')) + result = sorted( + policy.principals_allowed_by_permission(community, 'read') + ) self.assertEqual(result, ['chrism', 'mork', 'other']) - result = sorted(policy.principals_allowed_by_permission(community, - 'read')) + result = sorted( + policy.principals_allowed_by_permission(community, 'read') + ) result = sorted(policy.principals_allowed_by_permission(root, 'read')) self.assertEqual(result, ['chrism', 'jim', 'other']) def test_principals_allowed_by_permission_no_acls(self): context = DummyContext() policy = self._makeOne() - result = sorted(policy.principals_allowed_by_permission(context,'read')) + result = sorted( + policy.principals_allowed_by_permission(context, 'read') + ) self.assertEqual(result, []) def test_principals_allowed_by_permission_deny_not_permission_in_acl(self): from pyramid.security import Deny from pyramid.security import Everyone + context = DummyContext() - acl = [ (Deny, Everyone, 'write') ] + acl = [(Deny, Everyone, 'write')] context.__acl__ = acl policy = self._makeOne() result = sorted( - policy.principals_allowed_by_permission(context, 'read')) + policy.principals_allowed_by_permission(context, 'read') + ) self.assertEqual(result, []) def test_principals_allowed_by_permission_deny_permission_in_acl(self): from pyramid.security import Deny from pyramid.security import Everyone + context = DummyContext() - acl = [ (Deny, Everyone, 'read') ] + acl = [(Deny, Everyone, 'read')] context.__acl__ = acl policy = self._makeOne() result = sorted( - policy.principals_allowed_by_permission(context, 'read')) + policy.principals_allowed_by_permission(context, 'read') + ) self.assertEqual(result, []) def test_callable_acl(self): from pyramid.security import Allow + context = DummyContext() fn = lambda self: [(Allow, 'bob', 'read')] context.__acl__ = fn.__get__(context, context.__class__) policy = self._makeOne() result = policy.permits(context, ['bob'], 'read') self.assertTrue(result) - + class DummyContext: def __init__(self, *arg, **kw): @@ -256,4 +289,3 @@ GUEST_PERMS = (VIEW, COMMENT) MEMBER_PERMS = GUEST_PERMS + (EDIT, CREATE, DELETE) MODERATOR_PERMS = MEMBER_PERMS + (MODERATE,) ADMINISTRATOR_PERMS = MODERATOR_PERMS + (ADMINISTER,) - diff --git a/tests/test_compat.py b/tests/test_compat.py index 23ccce82e..46fc7d944 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -1,6 +1,7 @@ import unittest from pyramid.compat import is_unbound_method + class TestUnboundMethods(unittest.TestCase): def test_old_style_bound(self): self.assertFalse(is_unbound_method(OldStyle().run)) @@ -15,12 +16,17 @@ class TestUnboundMethods(unittest.TestCase): self.assertTrue(is_unbound_method(NewStyle.run)) def test_normal_func_unbound(self): - def func(): return 'OK' + def func(): + return 'OK' self.assertFalse(is_unbound_method(func)) + class OldStyle: - def run(self): return 'OK' + def run(self): + return 'OK' + class NewStyle(object): - def run(self): return 'OK' + def run(self): + return 'OK' diff --git a/tests/test_config/__init__.py b/tests/test_config/__init__.py index 81d9f4965..315e8c939 100644 --- a/tests/test_config/__init__.py +++ b/tests/test_config/__init__.py @@ -3,51 +3,70 @@ from zope.interface import implementer from zope.interface import Interface + class IFactory(Interface): pass -def dummy_tween_factory(handler, registry): pass -def dummy_tween_factory2(handler, registry): pass +def dummy_tween_factory(handler, registry): + pass + + +def dummy_tween_factory2(handler, registry): + pass + def dummy_include(config): config.registry.included = True config.action('discrim', None, config.package) + def dummy_include2(config): config.registry.also_included = True config.action('discrim', None, config.package) + includeme = dummy_include + class DummyContext: pass + @implementer(IFactory) class DummyFactory(object): def __call__(self): """ """ + def dummyfactory(request): """ """ + class IDummy(Interface): pass + def dummy_view(request): return 'OK' + def dummy_extend(config, discrim): config.action(discrim, None, config.package) + def dummy_extend2(config, discrim): config.action(discrim, None, config.registry) + from functools import partial + dummy_partial = partial(dummy_extend, discrim='partial') + class DummyCallable(object): def __call__(self, config, discrim): config.action(discrim, None, config.package) -dummy_callable = DummyCallable() + +dummy_callable = DummyCallable() diff --git a/tests/test_config/path/scanerror/__init__.py b/tests/test_config/path/scanerror/__init__.py index 86770ad89..934d6d3ad 100644 --- a/tests/test_config/path/scanerror/__init__.py +++ b/tests/test_config/path/scanerror/__init__.py @@ -1,3 +1 @@ # scan error package - - diff --git a/tests/test_config/pkgs/__init__.py b/tests/test_config/pkgs/__init__.py index ed88d78b4..5bb534f79 100644 --- a/tests/test_config/pkgs/__init__.py +++ b/tests/test_config/pkgs/__init__.py @@ -1,2 +1 @@ # package - diff --git a/tests/test_config/pkgs/asset/__init__.py b/tests/test_config/pkgs/asset/__init__.py index db5619fbc..5bb534f79 100644 --- a/tests/test_config/pkgs/asset/__init__.py +++ b/tests/test_config/pkgs/asset/__init__.py @@ -1,3 +1 @@ # package - - diff --git a/tests/test_config/pkgs/asset/subpackage/__init__.py b/tests/test_config/pkgs/asset/subpackage/__init__.py index d3173e636..5bb534f79 100644 --- a/tests/test_config/pkgs/asset/subpackage/__init__.py +++ b/tests/test_config/pkgs/asset/subpackage/__init__.py @@ -1 +1 @@ -#package +# package diff --git a/tests/test_config/pkgs/scanextrakw/__init__.py b/tests/test_config/pkgs/scanextrakw/__init__.py index ce5e07238..ddda504e1 100644 --- a/tests/test_config/pkgs/scanextrakw/__init__.py +++ b/tests/test_config/pkgs/scanextrakw/__init__.py @@ -1,14 +1,17 @@ import venusian + def foo(wrapped): def bar(scanner, name, wrapped): scanner.config.a = scanner.a + venusian.attach(wrapped, bar) return wrapped + @foo def hello(): pass -hello() # appease coverage +hello() # appease coverage diff --git a/tests/test_config/pkgs/scannable/__init__.py b/tests/test_config/pkgs/scannable/__init__.py index 562413a41..585f4357b 100644 --- a/tests/test_config/pkgs/scannable/__init__.py +++ b/tests/test_config/pkgs/scannable/__init__.py @@ -1,19 +1,23 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(renderer=null_renderer) def grokked(context, request): return 'grokked' + @view_config(request_method='POST', renderer=null_renderer) def grokked_post(context, request): return 'grokked_post' + @view_config(name='stacked2', renderer=null_renderer) @view_config(name='stacked1', renderer=null_renderer) def stacked(context, request): return 'stacked' + class stacked_class(object): def __init__(self, context, request): self.context = context @@ -22,11 +26,15 @@ class stacked_class(object): def __call__(self): return 'stacked_class' -stacked_class = view_config(name='stacked_class1', - renderer=null_renderer)(stacked_class) -stacked_class = view_config(name='stacked_class2', - renderer=null_renderer)(stacked_class) - + +stacked_class = view_config(name='stacked_class1', renderer=null_renderer)( + stacked_class +) +stacked_class = view_config(name='stacked_class2', renderer=null_renderer)( + stacked_class +) + + class oldstyle_grokked_class: def __init__(self, context, request): self.context = context @@ -34,10 +42,12 @@ class oldstyle_grokked_class: def __call__(self): return 'oldstyle_grokked_class' - -oldstyle_grokked_class = view_config(name='oldstyle_grokked_class', - renderer=null_renderer)( - oldstyle_grokked_class) + + +oldstyle_grokked_class = view_config( + name='oldstyle_grokked_class', renderer=null_renderer +)(oldstyle_grokked_class) + class grokked_class(object): def __init__(self, context, request): @@ -46,23 +56,30 @@ class grokked_class(object): def __call__(self): return 'grokked_class' - -grokked_class = view_config(name='grokked_class', - renderer=null_renderer)(grokked_class) + + +grokked_class = view_config(name='grokked_class', renderer=null_renderer)( + grokked_class +) + class Foo(object): def __call__(self, context, request): return 'grokked_instance' + grokked_instance = Foo() -grokked_instance = view_config(name='grokked_instance', - renderer=null_renderer)(grokked_instance) +grokked_instance = view_config( + name='grokked_instance', renderer=null_renderer +)(grokked_instance) + class Base(object): @view_config(name='basemethod', renderer=null_renderer) def basemethod(self): """ """ - + + class MethodViews(Base): def __init__(self, context, request): self.context = context @@ -81,16 +98,20 @@ class MethodViews(Base): def stacked(self): return 'stacked_method' + # ungrokkable A = 1 B = {} + def stuff(): """ """ + class Whatever(object): pass + class Whatever2: pass diff --git a/tests/test_config/pkgs/scannable/another.py b/tests/test_config/pkgs/scannable/another.py index 529821b5c..e8b71e5e3 100644 --- a/tests/test_config/pkgs/scannable/another.py +++ b/tests/test_config/pkgs/scannable/another.py @@ -1,19 +1,23 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(name='another', renderer=null_renderer) def grokked(context, request): return 'another_grokked' + @view_config(request_method='POST', name='another', renderer=null_renderer) def grokked_post(context, request): return 'another_grokked_post' + @view_config(name='another_stacked2', renderer=null_renderer) @view_config(name='another_stacked1', renderer=null_renderer) def stacked(context, request): return 'another_stacked' + class stacked_class(object): def __init__(self, context, request): self.context = context @@ -22,10 +26,14 @@ class stacked_class(object): def __call__(self): return 'another_stacked_class' -stacked_class = view_config(name='another_stacked_class1', - renderer=null_renderer)(stacked_class) -stacked_class = view_config(name='another_stacked_class2', - renderer=null_renderer)(stacked_class) + +stacked_class = view_config( + name='another_stacked_class1', renderer=null_renderer +)(stacked_class) +stacked_class = view_config( + name='another_stacked_class2', renderer=null_renderer +)(stacked_class) + class oldstyle_grokked_class: def __init__(self, context, request): @@ -34,10 +42,12 @@ class oldstyle_grokked_class: def __call__(self): return 'another_oldstyle_grokked_class' - -oldstyle_grokked_class = view_config(name='another_oldstyle_grokked_class', - renderer=null_renderer)( - oldstyle_grokked_class) + + +oldstyle_grokked_class = view_config( + name='another_oldstyle_grokked_class', renderer=null_renderer +)(oldstyle_grokked_class) + class grokked_class(object): def __init__(self, context, request): @@ -46,24 +56,28 @@ class grokked_class(object): def __call__(self): return 'another_grokked_class' - -grokked_class = view_config(name='another_grokked_class', - renderer=null_renderer)(grokked_class) + + +grokked_class = view_config( + name='another_grokked_class', renderer=null_renderer +)(grokked_class) + class Foo(object): def __call__(self, context, request): return 'another_grokked_instance' + grokked_instance = Foo() -grokked_instance = view_config(name='another_grokked_instance', - renderer=null_renderer)( - grokked_instance) +grokked_instance = view_config( + name='another_grokked_instance', renderer=null_renderer +)(grokked_instance) # ungrokkable A = 1 B = {} + def stuff(): """ """ - diff --git a/tests/test_config/pkgs/scannable/pod/notinit.py b/tests/test_config/pkgs/scannable/pod/notinit.py index 91dcd161b..03c93857f 100644 --- a/tests/test_config/pkgs/scannable/pod/notinit.py +++ b/tests/test_config/pkgs/scannable/pod/notinit.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(name='pod_notinit', renderer=null_renderer) def subpackage_notinit(context, request): return 'pod_notinit' diff --git a/tests/test_config/pkgs/scannable/subpackage/__init__.py b/tests/test_config/pkgs/scannable/subpackage/__init__.py index 9e0ddacbd..f89ca33f7 100644 --- a/tests/test_config/pkgs/scannable/subpackage/__init__.py +++ b/tests/test_config/pkgs/scannable/subpackage/__init__.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(name='subpackage_init', renderer=null_renderer) def subpackage_init(context, request): return 'subpackage_init' diff --git a/tests/test_config/pkgs/scannable/subpackage/notinit.py b/tests/test_config/pkgs/scannable/subpackage/notinit.py index f7edd0c68..65c2a4929 100644 --- a/tests/test_config/pkgs/scannable/subpackage/notinit.py +++ b/tests/test_config/pkgs/scannable/subpackage/notinit.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(name='subpackage_notinit', renderer=null_renderer) def subpackage_notinit(context, request): return 'subpackage_notinit' diff --git a/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py b/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py index fdda0dffe..ec4bab818 100644 --- a/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py +++ b/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py @@ -1,6 +1,7 @@ from pyramid.view import view_config from pyramid.renderers import null_renderer + @view_config(name='subsubpackage_init', renderer=null_renderer) def subpackage_init(context, request): return 'subsubpackage_init' diff --git a/tests/test_config/pkgs/selfscan/__init__.py b/tests/test_config/pkgs/selfscan/__init__.py index 779ea3eed..8bc8761ca 100644 --- a/tests/test_config/pkgs/selfscan/__init__.py +++ b/tests/test_config/pkgs/selfscan/__init__.py @@ -1,11 +1,14 @@ from pyramid.view import view_config + @view_config(renderer='string') def abc(request): return 'root' + def main(): from pyramid.config import Configurator + c = Configurator() c.scan() return c diff --git a/tests/test_config/pkgs/selfscan/another.py b/tests/test_config/pkgs/selfscan/another.py index a30ad3297..79e0b08de 100644 --- a/tests/test_config/pkgs/selfscan/another.py +++ b/tests/test_config/pkgs/selfscan/another.py @@ -1,6 +1,6 @@ from pyramid.view import view_config + @view_config(name='two', renderer='string') def two(request): return 'two' - diff --git a/tests/test_config/test_adapters.py b/tests/test_config/test_adapters.py index e554520e7..6237995d0 100644 --- a/tests/test_config/test_adapters.py +++ b/tests/test_config/test_adapters.py @@ -3,23 +3,30 @@ import unittest from pyramid.compat import PY2 from . import IDummy + class AdaptersConfiguratorMixinTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_add_subscriber_defaults(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] + def subscriber(event): L.append(event) + config = self._makeOne(autocommit=True) config.add_subscriber(subscriber) event = Event() @@ -32,14 +39,19 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_iface_specified(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] + def subscriber(event): L.append(event) + config = self._makeOne(autocommit=True) config.add_subscriber(subscriber, IEvent) event = Event() @@ -52,9 +64,11 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_dottednames(self): import tests.test_config from pyramid.interfaces import INewRequest + config = self._makeOne(autocommit=True) - config.add_subscriber('tests.test_config', - 'pyramid.interfaces.INewRequest') + config.add_subscriber( + 'tests.test_config', 'pyramid.interfaces.INewRequest' + ) handlers = list(config.registry.registeredHandlers()) self.assertEqual(len(handlers), 1) handler = handlers[0] @@ -64,15 +78,20 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_object_event_subscriber(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: object = 'foo' + event = Event() L = [] + def subscriber(object, event): L.append(event) + config = self._makeOne(autocommit=True) config.add_subscriber(subscriber, (Interface, IEvent)) config.registry.subscribers((event.object, event), None) @@ -84,14 +103,19 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_with_specific_type_and_predicates_True(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] + def subscriber(event): L.append(event) + config = self._makeOne(autocommit=True) predlist = config.get_predlist('subscriber') jam_predicate = predicate_maker('jam') @@ -111,14 +135,19 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_with_default_type_predicates_True(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] + def subscriber(event): L.append(event) + config = self._makeOne(autocommit=True) predlist = config.get_predlist('subscriber') jam_predicate = predicate_maker('jam') @@ -138,13 +167,19 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_with_specific_type_and_predicates_False(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] - def subscriber(event): L.append(event) + + def subscriber(event): + L.append(event) + config = self._makeOne(autocommit=True) predlist = config.get_predlist('subscriber') jam_predicate = predicate_maker('jam') @@ -161,13 +196,19 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_with_default_type_predicates_False(self): from zope.interface import implementer from zope.interface import Interface + class IEvent(Interface): pass + @implementer(IEvent) class Event: pass + L = [] - def subscriber(event): L.append(event) + + def subscriber(event): + L.append(event) + config = self._makeOne(autocommit=True) predlist = config.get_predlist('subscriber') jam_predicate = predicate_maker('jam') @@ -184,33 +225,42 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_subscriber_predicate(self): config = self._makeOne() L = [] - def add_predicate(type, name, factory, weighs_less_than=None, - weighs_more_than=None): + + def add_predicate( + type, name, factory, weighs_less_than=None, weighs_more_than=None + ): self.assertEqual(type, 'subscriber') self.assertEqual(name, 'name') self.assertEqual(factory, 'factory') self.assertEqual(weighs_more_than, 1) self.assertEqual(weighs_less_than, 2) L.append(1) + config._add_predicate = add_predicate config.add_subscriber_predicate('name', 'factory', 1, 2) self.assertTrue(L) - + def test_add_response_adapter(self): from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) + class Adapter(object): def __init__(self, other): self.other = other + config.add_response_adapter(Adapter, str) result = config.registry.queryAdapter('foo', IResponse) self.assertTrue(result.other, 'foo') def test_add_response_adapter_self(self): from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) + class Adapter(object): pass + config.add_response_adapter(None, Adapter) adapter = Adapter() result = config.registry.queryAdapter(adapter, IResponse) @@ -218,6 +268,7 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_response_adapter_dottednames(self): from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) if PY2: str_name = '__builtin__.str' @@ -229,10 +280,12 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_traverser_dotted_names(self): from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) config.add_traverser( 'tests.test_config.test_adapters.DummyTraverser', - 'tests.test_config.test_adapters.DummyIface') + 'tests.test_config.test_adapters.DummyIface', + ) iface = DummyIface() traverser = config.registry.getAdapter(iface, ITraverser) self.assertEqual(traverser.__class__, DummyTraverser) @@ -240,6 +293,7 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_traverser_default_iface_means_Interface(self): from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) config.add_traverser(DummyTraverser) traverser = config.registry.getAdapter(None, ITraverser) @@ -247,19 +301,20 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_traverser_nondefault_iface(self): from pyramid.interfaces import ITraverser + config = self._makeOne(autocommit=True) config.add_traverser(DummyTraverser, DummyIface) iface = DummyIface() traverser = config.registry.getAdapter(iface, ITraverser) self.assertEqual(traverser.__class__, DummyTraverser) self.assertEqual(traverser.root, iface) - + def test_add_traverser_introspectables(self): config = self._makeOne() config.add_traverser(DummyTraverser, DummyIface) actions = config.action_state.actions self.assertEqual(len(actions), 1) - intrs = actions[0]['introspectables'] + intrs = actions[0]['introspectables'] self.assertEqual(len(intrs), 1) intr = intrs[0] self.assertEqual(intr.type_name, 'traverser') @@ -271,25 +326,25 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_resource_url_adapter_dotted_names(self): from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) config.add_resource_url_adapter( 'tests.test_config.test_adapters.DummyResourceURL', 'tests.test_config.test_adapters.DummyIface', - ) + ) iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) + adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL) self.assertEqual(adapter.__class__, DummyResourceURL) self.assertEqual(adapter.resource, iface) self.assertEqual(adapter.request, iface) def test_add_resource_url_default_resource_iface_means_Interface(self): from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) config.add_resource_url_adapter(DummyResourceURL) iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) + adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL) self.assertEqual(adapter.__class__, DummyResourceURL) self.assertEqual(adapter.resource, iface) self.assertEqual(adapter.request, iface) @@ -297,18 +352,17 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_resource_url_nodefault_resource_iface(self): from zope.interface import Interface from pyramid.interfaces import IResourceURL + config = self._makeOne(autocommit=True) config.add_resource_url_adapter(DummyResourceURL, DummyIface) iface = DummyIface() - adapter = config.registry.getMultiAdapter((iface, iface), - IResourceURL) + adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL) self.assertEqual(adapter.__class__, DummyResourceURL) self.assertEqual(adapter.resource, iface) self.assertEqual(adapter.request, iface) bad_result = config.registry.queryMultiAdapter( - (Interface, Interface), - IResourceURL, - ) + (Interface, Interface), IResourceURL + ) self.assertEqual(bad_result, None) def test_add_resource_url_adapter_introspectables(self): @@ -316,50 +370,62 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): config.add_resource_url_adapter(DummyResourceURL, DummyIface) actions = config.action_state.actions self.assertEqual(len(actions), 1) - intrs = actions[0]['introspectables'] + intrs = actions[0]['introspectables'] self.assertEqual(len(intrs), 1) intr = intrs[0] self.assertEqual(intr.type_name, 'resource url adapter') - self.assertEqual(intr.discriminator, - ('resource url adapter', DummyIface)) + self.assertEqual( + intr.discriminator, ('resource url adapter', DummyIface) + ) self.assertEqual(intr.category_name, 'resource url adapters') self.assertEqual( intr.title, "resource url adapter for resource iface " - "<class 'tests.test_config.test_adapters.DummyIface'>" - ) + "<class 'tests.test_config.test_adapters.DummyIface'>", + ) self.assertEqual(intr['adapter'], DummyResourceURL) self.assertEqual(intr['resource_iface'], DummyIface) + class Test_eventonly(unittest.TestCase): def _callFUT(self, callee): from pyramid.config.adapters import eventonly + return eventonly(callee) def test_defaults(self): - def acallable(event, a=1, b=2): pass + def acallable(event, a=1, b=2): + pass + self.assertTrue(self._callFUT(acallable)) + class DummyTraverser(object): def __init__(self, root): self.root = root + class DummyIface(object): pass + class DummyResourceURL(object): def __init__(self, resource, request): self.resource = resource self.request = request - + + def predicate_maker(name): class Predicate(object): def __init__(self, val, config): self.val = val + def phash(self): return 'phash' + text = phash + def __call__(self, event): return getattr(event, name, None) == self.val - return Predicate + return Predicate diff --git a/tests/test_config/test_assets.py b/tests/test_config/test_assets.py index b16977b99..875846dbd 100644 --- a/tests/test_config/test_assets.py +++ b/tests/test_config/test_assets.py @@ -5,48 +5,66 @@ from pyramid.testing import cleanUp # we use this folder here = os.path.dirname(os.path.abspath(__file__)) + class TestAssetsConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_override_asset_samename(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() self.assertRaises(ConfigurationError, config.override_asset, 'a', 'a') def test_override_asset_directory_with_file(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo/', - 'tests.test_config.pkgs.asset:foo.pt') + self.assertRaises( + ConfigurationError, + config.override_asset, + 'a:foo/', + 'tests.test_config.pkgs.asset:foo.pt', + ) def test_override_asset_file_with_directory(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', - 'tests.test_config.pkgs.asset:templates/') + self.assertRaises( + ConfigurationError, + config.override_asset, + 'a:foo.pt', + 'tests.test_config.pkgs.asset:templates/', + ) def test_override_asset_file_with_package(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', - 'tests.test_config.pkgs.asset') + self.assertRaises( + ConfigurationError, + config.override_asset, + 'a:foo.pt', + 'tests.test_config.pkgs.asset', + ) def test_override_asset_file_with_file(self): from pyramid.config.assets import PackageAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( 'tests.test_config.pkgs.asset:templates/foo.pt', 'tests.test_config.pkgs.asset.subpackage:templates/bar.pt', - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset from tests.test_config.pkgs.asset import subpackage + self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/foo.pt') source = override.source @@ -55,21 +73,24 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, 'templates/bar.pt') resource_name = '' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_package_with_package(self): from pyramid.config.assets import PackageAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( 'tests.test_config.pkgs.asset', 'tests.test_config.pkgs.asset.subpackage', - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset from tests.test_config.pkgs.asset import subpackage + self.assertEqual(override.package, asset) self.assertEqual(override.path, '') source = override.source @@ -78,21 +99,24 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, '') resource_name = 'templates/bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_directory_with_directory(self): from pyramid.config.assets import PackageAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( 'tests.test_config.pkgs.asset:templates/', 'tests.test_config.pkgs.asset.subpackage:templates/', - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset from tests.test_config.pkgs.asset import subpackage + self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/') source = override.source @@ -101,21 +125,24 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, 'templates/') resource_name = 'bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_directory_with_package(self): from pyramid.config.assets import PackageAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( 'tests.test_config.pkgs.asset:templates/', 'tests.test_config.pkgs.asset.subpackage', - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset from tests.test_config.pkgs.asset import subpackage + self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/') source = override.source @@ -124,21 +151,24 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, '') resource_name = 'templates/bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_package_with_directory(self): from pyramid.config.assets import PackageAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( 'tests.test_config.pkgs.asset', 'tests.test_config.pkgs.asset.subpackage:templates/', - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset from tests.test_config.pkgs.asset import subpackage + self.assertEqual(override.package, asset) self.assertEqual(override.path, '') source = override.source @@ -147,44 +177,59 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, 'templates/') resource_name = 'bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_directory_with_absfile(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo/', - os.path.join(here, 'pkgs', 'asset', 'foo.pt')) + self.assertRaises( + ConfigurationError, + config.override_asset, + 'a:foo/', + os.path.join(here, 'pkgs', 'asset', 'foo.pt'), + ) def test_override_asset_file_with_absdirectory(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', - abspath) + abspath = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates' + ) + self.assertRaises( + ConfigurationError, config.override_asset, 'a:foo.pt', abspath + ) def test_override_asset_file_with_missing_abspath(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', - os.path.join(here, 'wont_exist')) + self.assertRaises( + ConfigurationError, + config.override_asset, + 'a:foo.pt', + os.path.join(here, 'wont_exist'), + ) def test_override_asset_file_with_absfile(self): from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() - abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', - 'templates', 'bar.pt') + abspath = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) config.override_asset( 'tests.test_config.pkgs.asset:templates/foo.pt', abspath, - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/foo.pt') source = override.source @@ -192,21 +237,26 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, abspath) resource_name = '' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_directory_with_absdirectory(self): from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() - abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') + abspath = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates' + ) config.override_asset( 'tests.test_config.pkgs.asset:templates/', abspath, - _override=override) + _override=override, + ) from tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/') source = override.source @@ -214,21 +264,24 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, abspath) resource_name = 'bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test_override_asset_package_with_absdirectory(self): from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) override = DummyUnderOverride() - abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') + abspath = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates' + ) config.override_asset( - 'tests.test_config.pkgs.asset', - abspath, - _override=override) + 'tests.test_config.pkgs.asset', abspath, _override=override + ) from tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) self.assertEqual(override.path, '') source = override.source @@ -236,33 +289,39 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): self.assertEqual(source.prefix, abspath) resource_name = 'bar.pt' - expected = os.path.join(here, 'pkgs', 'asset', - 'subpackage', 'templates', 'bar.pt') - self.assertEqual(override.source.get_filename(resource_name), - expected) + expected = os.path.join( + here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt' + ) + self.assertEqual(override.source.get_filename(resource_name), expected) def test__override_not_yet_registered(self): from pyramid.interfaces import IPackageOverrides + package = DummyPackage('package') source = DummyAssetSource() config = self._makeOne() - config._override(package, 'path', source, - PackageOverrides=DummyPackageOverrides) - overrides = config.registry.queryUtility(IPackageOverrides, - name='package') + config._override( + package, 'path', source, PackageOverrides=DummyPackageOverrides + ) + overrides = config.registry.queryUtility( + IPackageOverrides, name='package' + ) self.assertEqual(overrides.inserted, [('path', source)]) self.assertEqual(overrides.package, package) def test__override_already_registered(self): from pyramid.interfaces import IPackageOverrides + package = DummyPackage('package') source = DummyAssetSource() overrides = DummyPackageOverrides(package) config = self._makeOne() - config.registry.registerUtility(overrides, IPackageOverrides, - name='package') - config._override(package, 'path', source, - PackageOverrides=DummyPackageOverrides) + config.registry.registerUtility( + overrides, IPackageOverrides, name='package' + ) + config._override( + package, 'path', source, PackageOverrides=DummyPackageOverrides + ) self.assertEqual(overrides.inserted, [('path', source)]) self.assertEqual(overrides.package, package) @@ -276,6 +335,7 @@ class TestOverrideProvider(unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import OverrideProvider + return OverrideProvider def _makeOne(self, module): @@ -285,12 +345,14 @@ class TestOverrideProvider(unittest.TestCase): def _registerOverrides(self, overrides, name='tests.test_config'): from pyramid.interfaces import IPackageOverrides from pyramid.threadlocal import get_current_registry + reg = get_current_registry() reg.registerUtility(overrides, IPackageOverrides, name=name) def test_get_resource_filename_no_overrides(self): resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) expected = os.path.join(here, resource_name) result = provider.get_resource_filename(None, resource_name) @@ -299,6 +361,7 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_stream_no_overrides(self): resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) with provider.get_resource_stream(None, resource_name) as result: _assertBody(result.read(), os.path.join(here, resource_name)) @@ -306,6 +369,7 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_string_no_overrides(self): resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.get_resource_string(None, resource_name) _assertBody(result, os.path.join(here, resource_name)) @@ -313,6 +377,7 @@ class TestOverrideProvider(unittest.TestCase): def test_has_resource_no_overrides(self): resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.has_resource(resource_name) self.assertEqual(result, True) @@ -321,6 +386,7 @@ class TestOverrideProvider(unittest.TestCase): file_resource_name = 'test_assets.py' directory_resource_name = 'files' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.resource_isdir(file_resource_name) self.assertEqual(result, False) @@ -330,6 +396,7 @@ class TestOverrideProvider(unittest.TestCase): def test_resource_listdir_no_overrides(self): resource_name = 'files' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.resource_listdir(resource_name) self.assertTrue(result) @@ -339,16 +406,18 @@ class TestOverrideProvider(unittest.TestCase): self._registerOverrides(overrides) resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) expected = os.path.join(here, resource_name) result = provider.get_resource_filename(None, resource_name) self.assertEqual(result, expected) - + def test_get_resource_stream_override_returns_None(self): overrides = DummyOverrides(None) self._registerOverrides(overrides) resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) with provider.get_resource_stream(None, resource_name) as result: _assertBody(result.read(), os.path.join(here, resource_name)) @@ -358,6 +427,7 @@ class TestOverrideProvider(unittest.TestCase): self._registerOverrides(overrides) resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.get_resource_string(None, resource_name) _assertBody(result, os.path.join(here, resource_name)) @@ -367,6 +437,7 @@ class TestOverrideProvider(unittest.TestCase): self._registerOverrides(overrides) resource_name = 'test_assets.py' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.has_resource(resource_name) self.assertEqual(result, True) @@ -376,6 +447,7 @@ class TestOverrideProvider(unittest.TestCase): self._registerOverrides(overrides) resource_name = 'files' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.resource_isdir(resource_name) self.assertEqual(result, True) @@ -385,6 +457,7 @@ class TestOverrideProvider(unittest.TestCase): self._registerOverrides(overrides) resource_name = 'files' import tests.test_config + provider = self._makeOne(tests.test_config) result = provider.resource_listdir(resource_name) self.assertTrue(result) @@ -392,6 +465,7 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_filename_override_returns_value(self): overrides = DummyOverrides('value') import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) result = provider.get_resource_filename(None, 'test_assets.py') @@ -399,8 +473,10 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_stream_override_returns_value(self): from io import BytesIO + overrides = DummyOverrides(BytesIO(b'value')) import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) with provider.get_resource_stream(None, 'test_assets.py') as stream: @@ -409,6 +485,7 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_string_override_returns_value(self): overrides = DummyOverrides('value') import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) result = provider.get_resource_string(None, 'test_assets.py') @@ -417,6 +494,7 @@ class TestOverrideProvider(unittest.TestCase): def test_has_resource_override_returns_True(self): overrides = DummyOverrides(True) import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) result = provider.has_resource('test_assets.py') @@ -425,6 +503,7 @@ class TestOverrideProvider(unittest.TestCase): def test_resource_isdir_override_returns_False(self): overrides = DummyOverrides(False) import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) result = provider.resource_isdir('files') @@ -433,14 +512,17 @@ class TestOverrideProvider(unittest.TestCase): def test_resource_listdir_override_returns_values(self): overrides = DummyOverrides(['a']) import tests.test_config + self._registerOverrides(overrides) provider = self._makeOne(tests.test_config) result = provider.resource_listdir('files') self.assertEqual(result, ['a']) + class TestPackageOverrides(unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import PackageOverrides + return PackageOverrides def _makeOne(self, package=None, pkg_resources=None): @@ -454,21 +536,25 @@ class TestPackageOverrides(unittest.TestCase): def test_class_conforms_to_IPackageOverrides(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IPackageOverrides + verifyClass(IPackageOverrides, self._getTargetClass()) def test_instance_conforms_to_IPackageOverrides(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IPackageOverrides + verifyObject(IPackageOverrides, self._makeOne()) def test_class_conforms_to_IPEP302Loader(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IPEP302Loader + verifyClass(IPEP302Loader, self._getTargetClass()) def test_instance_conforms_to_IPEP302Loader(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IPEP302Loader + verifyObject(IPEP302Loader, self._makeOne()) def test_ctor_package_already_has_loader_of_different_type(self): @@ -491,11 +577,13 @@ class TestPackageOverrides(unittest.TestCase): def test_ctor_registers_loader_type(self): from pyramid.config.assets import OverrideProvider + dummy_pkg_resources = DummyPkgResources() package = DummyPackage('package') po = self._makeOne(package, dummy_pkg_resources) - self.assertEqual(dummy_pkg_resources.registered, [(po.__class__, - OverrideProvider)]) + self.assertEqual( + dummy_pkg_resources.registered, [(po.__class__, OverrideProvider)] + ) def test_ctor_sets_local_state(self): package = DummyPackage('package') @@ -505,6 +593,7 @@ class TestPackageOverrides(unittest.TestCase): def test_insert_directory(self): from pyramid.config.assets import DirectoryOverride + package = DummyPackage('package') po = self._makeOne(package) po.overrides = [None] @@ -515,6 +604,7 @@ class TestPackageOverrides(unittest.TestCase): def test_insert_file(self): from pyramid.config.assets import FileOverride + package = DummyPackage('package') po = self._makeOne(package) po.overrides = [None] @@ -526,6 +616,7 @@ class TestPackageOverrides(unittest.TestCase): def test_insert_emptystring(self): # XXX is this a valid case for a directory? from pyramid.config.assets import DirectoryOverride + package = DummyPackage('package') po = self._makeOne(package) po.overrides = [None] @@ -536,7 +627,7 @@ class TestPackageOverrides(unittest.TestCase): self.assertEqual(override.__class__, DirectoryOverride) def test_filtered_sources(self): - overrides = [ DummyOverride(None), DummyOverride('foo')] + overrides = [DummyOverride(None), DummyOverride('foo')] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -544,7 +635,7 @@ class TestPackageOverrides(unittest.TestCase): def test_get_filename(self): source = DummyAssetSource(filename='foo.pt') - overrides = [ DummyOverride(None), DummyOverride((source, ''))] + overrides = [DummyOverride(None), DummyOverride((source, ''))] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -554,7 +645,10 @@ class TestPackageOverrides(unittest.TestCase): def test_get_filename_file_doesnt_exist(self): source = DummyAssetSource(filename=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -569,10 +663,13 @@ class TestPackageOverrides(unittest.TestCase): po.overrides = overrides self.assertEqual(po.get_stream('whatever'), 'a stream?') self.assertEqual(source.resource_name, 'foo.pt') - + def test_get_stream_file_doesnt_exist(self): source = DummyAssetSource(stream=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -587,10 +684,13 @@ class TestPackageOverrides(unittest.TestCase): po.overrides = overrides self.assertEqual(po.get_string('whatever'), 'a string') self.assertEqual(source.resource_name, 'foo.pt') - + def test_get_string_file_doesnt_exist(self): source = DummyAssetSource(string=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -608,7 +708,10 @@ class TestPackageOverrides(unittest.TestCase): def test_has_resource_file_doesnt_exist(self): source = DummyAssetSource(exists=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -635,7 +738,10 @@ class TestPackageOverrides(unittest.TestCase): def test_isdir_doesnt_exist(self): source = DummyAssetSource(isdir=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -653,7 +759,10 @@ class TestPackageOverrides(unittest.TestCase): def test_listdir_doesnt_exist(self): source = DummyAssetSource(listdir=None) - overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] + overrides = [ + DummyOverride(None), + DummyOverride((source, 'wont_exist')), + ] package = DummyPackage('package') po = self._makeOne(package) po.overrides = overrides @@ -668,7 +777,7 @@ class TestPackageOverrides(unittest.TestCase): def test_get_data_pkg_has___loader__(self): package = DummyPackage('package') - loader = package.__loader__ = DummyLoader() + loader = package.__loader__ = DummyLoader() po = self._makeOne(package) self.assertEqual(po.get_data('whatever'), b'DEADBEEF') self.assertEqual(loader._got_data, 'whatever') @@ -680,7 +789,7 @@ class TestPackageOverrides(unittest.TestCase): def test_is_package_pkg_has___loader__(self): package = DummyPackage('package') - loader = package.__loader__ = DummyLoader() + loader = package.__loader__ = DummyLoader() po = self._makeOne(package) self.assertTrue(po.is_package('whatever')) self.assertEqual(loader._is_package, 'whatever') @@ -692,7 +801,7 @@ class TestPackageOverrides(unittest.TestCase): def test_get_code_pkg_has___loader__(self): package = DummyPackage('package') - loader = package.__loader__ = DummyLoader() + loader = package.__loader__ = DummyLoader() po = self._makeOne(package) self.assertEqual(po.get_code('whatever'), b'DEADBEEF') self.assertEqual(loader._got_code, 'whatever') @@ -709,17 +818,20 @@ class TestPackageOverrides(unittest.TestCase): self.assertEqual(po.get_source('whatever'), 'def foo():\n pass') self.assertEqual(loader._got_source, 'whatever') -class AssetSourceIntegrationTests(object): +class AssetSourceIntegrationTests(object): def test_get_filename(self): source = self._makeOne('') - self.assertEqual(source.get_filename('test_assets.py'), - os.path.join(here, 'test_assets.py')) + self.assertEqual( + source.get_filename('test_assets.py'), + os.path.join(here, 'test_assets.py'), + ) def test_get_filename_with_prefix(self): source = self._makeOne('test_assets.py') - self.assertEqual(source.get_filename(''), - os.path.join(here, 'test_assets.py')) + self.assertEqual( + source.get_filename(''), os.path.join(here, 'test_assets.py') + ) def test_get_filename_file_doesnt_exist(self): source = self._makeOne('') @@ -741,13 +853,16 @@ class AssetSourceIntegrationTests(object): def test_get_string(self): source = self._makeOne('') - _assertBody(source.get_string('test_assets.py'), - os.path.join(here, 'test_assets.py')) + _assertBody( + source.get_string('test_assets.py'), + os.path.join(here, 'test_assets.py'), + ) def test_get_string_with_prefix(self): source = self._makeOne('test_assets.py') - _assertBody(source.get_string(''), - os.path.join(here, 'test_assets.py')) + _assertBody( + source.get_string(''), os.path.join(here, 'test_assets.py') + ) def test_get_string_file_doesnt_exist(self): source = self._makeOne('') @@ -785,28 +900,33 @@ class AssetSourceIntegrationTests(object): source = self._makeOne('') self.assertEqual(source.listdir('wont_exist'), None) -class TestPackageAssetSource(AssetSourceIntegrationTests, unittest.TestCase): +class TestPackageAssetSource(AssetSourceIntegrationTests, unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import PackageAssetSource + return PackageAssetSource def _makeOne(self, prefix, package='tests.test_config'): klass = self._getTargetClass() return klass(package, prefix) + class TestFSAssetSource(AssetSourceIntegrationTests, unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import FSAssetSource + return FSAssetSource def _makeOne(self, prefix, base_prefix=here): klass = self._getTargetClass() return klass(os.path.join(base_prefix, prefix)) + class TestDirectoryOverride(unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import DirectoryOverride + return DirectoryOverride def _makeOne(self, path, source): @@ -818,16 +938,18 @@ class TestDirectoryOverride(unittest.TestCase): o = self._makeOne('foo/', source) result = o('foo/something.pt') self.assertEqual(result, (source, 'something.pt')) - + def test_it_no_match(self): source = DummyAssetSource() o = self._makeOne('foo/', source) result = o('baz/notfound.pt') self.assertEqual(result, None) + class TestFileOverride(unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import FileOverride + return FileOverride def _makeOne(self, path, source): @@ -839,13 +961,14 @@ class TestFileOverride(unittest.TestCase): o = self._makeOne('foo.pt', source) result = o('foo.pt') self.assertEqual(result, (source, '')) - + def test_it_no_match(self): source = DummyAssetSource() o = self._makeOne('foo.pt', source) result = o('notfound.pt') self.assertEqual(result, None) + class DummyOverride: def __init__(self, result): self.result = result @@ -853,6 +976,7 @@ class DummyOverride: def __call__(self, resource_name): return self.result + class DummyOverrides: def __init__(self, result): self.result = result @@ -862,6 +986,7 @@ class DummyOverrides: listdir = isdir = has_resource = get_stream = get_string = get_filename + class DummyPackageOverrides: def __init__(self, package): self.package = package @@ -869,7 +994,8 @@ class DummyPackageOverrides: def insert(self, path, source): self.inserted.append((path, source)) - + + class DummyPkgResources: def __init__(self): self.registered = [] @@ -877,10 +1003,12 @@ class DummyPkgResources: def register_loader_type(self, typ, inst): self.registered.append((typ, inst)) + class DummyPackage: def __init__(self, name): self.__name__ = name + class DummyAssetSource: def __init__(self, **kw): self.kw = kw @@ -908,33 +1036,41 @@ class DummyAssetSource: def listdir(self, resource_name): self.resource_name = resource_name return self.kw['listdir'] - + + class DummyLoader: _got_data = _is_package = None + def get_data(self, path): self._got_data = path return b'DEADBEEF' + def is_package(self, fullname): self._is_package = fullname return True + def get_code(self, fullname): self._got_code = fullname return b'DEADBEEF' + def get_source(self, fullname): self._got_source = fullname return 'def foo():\n pass' + class DummyUnderOverride: def __call__(self, package, path, source, _info=''): self.package = package self.path = path self.source = source + def read_(src): with open(src, 'rb') as f: contents = f.read() return contents + def _assertBody(body, filename): # strip both \n and \r for windows body = body.replace(b'\r', b'') @@ -942,4 +1078,4 @@ def _assertBody(body, filename): data = read_(filename) data = data.replace(b'\r', b'') data = data.replace(b'\n', b'') - assert(body == data) + assert body == data diff --git a/tests/test_config/test_factories.py b/tests/test_config/test_factories.py index ea8dec720..325ba52f3 100644 --- a/tests/test_config/test_factories.py +++ b/tests/test_config/test_factories.py @@ -2,14 +2,17 @@ import unittest from . import dummyfactory + class TestFactoriesMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_set_request_factory(self): from pyramid.interfaces import IRequestFactory + config = self._makeOne(autocommit=True) factory = object() config.set_request_factory(factory) @@ -17,14 +20,16 @@ class TestFactoriesMixin(unittest.TestCase): def test_set_request_factory_dottedname(self): from pyramid.interfaces import IRequestFactory + config = self._makeOne(autocommit=True) - config.set_request_factory( - 'tests.test_config.dummyfactory') - self.assertEqual(config.registry.getUtility(IRequestFactory), - dummyfactory) + config.set_request_factory('tests.test_config.dummyfactory') + self.assertEqual( + config.registry.getUtility(IRequestFactory), dummyfactory + ) def test_set_response_factory(self): from pyramid.interfaces import IResponseFactory + config = self._makeOne(autocommit=True) factory = lambda r: object() config.set_response_factory(factory) @@ -32,58 +37,72 @@ class TestFactoriesMixin(unittest.TestCase): def test_set_response_factory_dottedname(self): from pyramid.interfaces import IResponseFactory + config = self._makeOne(autocommit=True) - config.set_response_factory( - 'tests.test_config.dummyfactory') - self.assertEqual(config.registry.getUtility(IResponseFactory), - dummyfactory) + config.set_response_factory('tests.test_config.dummyfactory') + self.assertEqual( + config.registry.getUtility(IResponseFactory), dummyfactory + ) def test_set_root_factory(self): from pyramid.interfaces import IRootFactory + config = self._makeOne() config.set_root_factory(dummyfactory) self.assertEqual(config.registry.queryUtility(IRootFactory), None) config.commit() - self.assertEqual(config.registry.getUtility(IRootFactory), dummyfactory) + self.assertEqual( + config.registry.getUtility(IRootFactory), dummyfactory + ) def test_set_root_factory_as_None(self): from pyramid.interfaces import IRootFactory from pyramid.traversal import DefaultRootFactory + config = self._makeOne() config.set_root_factory(None) self.assertEqual(config.registry.queryUtility(IRootFactory), None) config.commit() - self.assertEqual(config.registry.getUtility(IRootFactory), - DefaultRootFactory) + self.assertEqual( + config.registry.getUtility(IRootFactory), DefaultRootFactory + ) def test_set_root_factory_dottedname(self): from pyramid.interfaces import IRootFactory + config = self._makeOne() config.set_root_factory('tests.test_config.dummyfactory') self.assertEqual(config.registry.queryUtility(IRootFactory), None) config.commit() - self.assertEqual(config.registry.getUtility(IRootFactory), dummyfactory) + self.assertEqual( + config.registry.getUtility(IRootFactory), dummyfactory + ) def test_set_session_factory(self): from pyramid.interfaces import ISessionFactory + config = self._makeOne() config.set_session_factory(dummyfactory) self.assertEqual(config.registry.queryUtility(ISessionFactory), None) config.commit() - self.assertEqual(config.registry.getUtility(ISessionFactory), - dummyfactory) + self.assertEqual( + config.registry.getUtility(ISessionFactory), dummyfactory + ) def test_set_session_factory_dottedname(self): from pyramid.interfaces import ISessionFactory + config = self._makeOne() config.set_session_factory('tests.test_config.dummyfactory') self.assertEqual(config.registry.queryUtility(ISessionFactory), None) config.commit() - self.assertEqual(config.registry.getUtility(ISessionFactory), - dummyfactory) + self.assertEqual( + config.registry.getUtility(ISessionFactory), dummyfactory + ) def test_add_request_method_with_callable(self): from pyramid.interfaces import IRequestExtensions + config = self._makeOne(autocommit=True) callable = lambda x: None config.add_request_method(callable, name='foo') @@ -92,23 +111,34 @@ class TestFactoriesMixin(unittest.TestCase): def test_add_request_method_with_unnamed_callable(self): from pyramid.interfaces import IRequestExtensions + config = self._makeOne(autocommit=True) - def foo(self): pass + + def foo(self): + pass + config.add_request_method(foo) exts = config.registry.getUtility(IRequestExtensions) self.assertTrue('foo' in exts.methods) def test_set_multiple_request_methods_conflict(self): from pyramid.exceptions import ConfigurationConflictError + config = self._makeOne() - def foo(self): pass - def bar(self): pass + + def foo(self): + pass + + def bar(self): + pass + config.add_request_method(foo, name='bar') config.add_request_method(bar, name='bar') self.assertRaises(ConfigurationConflictError, config.commit) def test_add_request_method_with_None_callable(self): from pyramid.interfaces import IRequestExtensions + config = self._makeOne(autocommit=True) config.add_request_method(name='foo') exts = config.registry.queryUtility(IRequestExtensions) @@ -116,8 +146,12 @@ class TestFactoriesMixin(unittest.TestCase): def test_add_request_method_with_None_callable_conflict(self): from pyramid.exceptions import ConfigurationConflictError + config = self._makeOne() - def bar(self): pass + + def bar(self): + pass + config.add_request_method(name='foo') config.add_request_method(bar, name='foo') self.assertRaises(ConfigurationConflictError, config.commit) @@ -132,7 +166,9 @@ class TestFactoriesMixin(unittest.TestCase): from pyramid.exceptions import ConfigurationError config = self._makeOne(autocommit=True) - def boomshaka(r): pass + + def boomshaka(r): + pass def get_bad_name(): if PY2: @@ -146,8 +182,12 @@ class TestFactoriesMixin(unittest.TestCase): def test_set_execution_policy(self): from pyramid.interfaces import IExecutionPolicy + config = self._makeOne(autocommit=True) - def dummy_policy(environ, router): pass + + def dummy_policy(environ, router): + pass + config.set_execution_policy(dummy_policy) registry = config.registry result = registry.queryUtility(IExecutionPolicy) @@ -156,6 +196,7 @@ class TestFactoriesMixin(unittest.TestCase): def test_set_execution_policy_to_None(self): from pyramid.interfaces import IExecutionPolicy from pyramid.router import default_execution_policy + config = self._makeOne(autocommit=True) config.set_execution_policy(None) registry = config.registry diff --git a/tests/test_config/test_i18n.py b/tests/test_config/test_i18n.py index 87805f671..5961e9ff2 100644 --- a/tests/test_config/test_i18n.py +++ b/tests/test_config/test_i18n.py @@ -5,56 +5,73 @@ from . import dummyfactory here = os.path.dirname(__file__) locale = os.path.abspath( - os.path.join(here, '..', 'pkgs', 'localeapp', 'locale')) + os.path.join(here, '..', 'pkgs', 'localeapp', 'locale') +) locale2 = os.path.abspath( - os.path.join(here, '..', 'pkgs', 'localeapp', 'locale2')) + os.path.join(here, '..', 'pkgs', 'localeapp', 'locale2') +) locale3 = os.path.abspath( - os.path.join(here, '..', 'pkgs', 'localeapp', 'locale3')) + os.path.join(here, '..', 'pkgs', 'localeapp', 'locale3') +) + class TestI18NConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_set_locale_negotiator(self): from pyramid.interfaces import ILocaleNegotiator + config = self._makeOne(autocommit=True) - def negotiator(request): pass + + def negotiator(request): + pass + config.set_locale_negotiator(negotiator) - self.assertEqual(config.registry.getUtility(ILocaleNegotiator), - negotiator) + self.assertEqual( + config.registry.getUtility(ILocaleNegotiator), negotiator + ) def test_set_locale_negotiator_dottedname(self): from pyramid.interfaces import ILocaleNegotiator + config = self._makeOne(autocommit=True) - config.set_locale_negotiator( - 'tests.test_config.dummyfactory') - self.assertEqual(config.registry.getUtility(ILocaleNegotiator), - dummyfactory) + config.set_locale_negotiator('tests.test_config.dummyfactory') + self.assertEqual( + config.registry.getUtility(ILocaleNegotiator), dummyfactory + ) def test_add_translation_dirs_missing_dir(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() config.add_translation_dirs('/wont/exist/on/my/system') self.assertRaises(ConfigurationError, config.commit) def test_add_translation_dirs_no_specs(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne() config.add_translation_dirs() - self.assertEqual(config.registry.queryUtility(ITranslationDirectories), - None) + self.assertEqual( + config.registry.queryUtility(ITranslationDirectories), None + ) def test_add_translation_dirs_asset_spec(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) config.add_translation_dirs('tests.pkgs.localeapp:locale') - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale]) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), [locale] + ) def test_add_translation_dirs_asset_spec_existing_translation_dirs(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) directories = ['abc'] config.registry.registerUtility(directories, ITranslationDirectories) @@ -64,69 +81,93 @@ class TestI18NConfiguratorMixin(unittest.TestCase): def test_add_translation_dirs_multiple_specs(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) - config.add_translation_dirs('tests.pkgs.localeapp:locale', - 'tests.pkgs.localeapp:locale2') - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale, locale2]) + config.add_translation_dirs( + 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2' + ) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), + [locale, locale2], + ) def test_add_translation_dirs_multiple_specs_multiple_calls(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) - config.add_translation_dirs('tests.pkgs.localeapp:locale', - 'tests.pkgs.localeapp:locale2') + config.add_translation_dirs( + 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2' + ) config.add_translation_dirs('tests.pkgs.localeapp:locale3') - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale3, locale, locale2]) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), + [locale3, locale, locale2], + ) def test_add_translation_dirs_override_multiple_specs_multiple_calls(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) - config.add_translation_dirs('tests.pkgs.localeapp:locale', - 'tests.pkgs.localeapp:locale2') - config.add_translation_dirs('tests.pkgs.localeapp:locale3', - override=True) - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale, locale2, locale3]) + config.add_translation_dirs( + 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2' + ) + config.add_translation_dirs( + 'tests.pkgs.localeapp:locale3', override=True + ) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), + [locale, locale2, locale3], + ) def test_add_translation_dirs_invalid_kwargs(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) with self.assertRaises(TypeError): - config.add_translation_dirs('tests.pkgs.localeapp:locale', - foo=1) + config.add_translation_dirs('tests.pkgs.localeapp:locale', foo=1) def test_add_translation_dirs_abspath(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) config.add_translation_dirs(locale) - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale]) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), [locale] + ) def test_add_translation_dirs_uses_override_out_of_order(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne() config.add_translation_dirs('tests.pkgs.localeapp:locale') - config.override_asset('tests.pkgs.localeapp:locale/', - 'tests.pkgs.localeapp:locale2/') + config.override_asset( + 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/' + ) config.commit() - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale2]) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), [locale2] + ) def test_add_translation_dirs_doesnt_use_override_w_autocommit(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) config.add_translation_dirs('tests.pkgs.localeapp:locale') - config.override_asset('tests.pkgs.localeapp:locale/', - 'tests.pkgs.localeapp:locale2/') - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale]) + config.override_asset( + 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/' + ) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), [locale] + ) def test_add_translation_dirs_uses_override_w_autocommit(self): from pyramid.interfaces import ITranslationDirectories + config = self._makeOne(autocommit=True) - config.override_asset('tests.pkgs.localeapp:locale/', - 'tests.pkgs.localeapp:locale2/') + config.override_asset( + 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/' + ) config.add_translation_dirs('tests.pkgs.localeapp:locale') - self.assertEqual(config.registry.getUtility(ITranslationDirectories), - [locale2]) + self.assertEqual( + config.registry.getUtility(ITranslationDirectories), [locale2] + ) diff --git a/tests/test_config/test_init.py b/tests/test_config/test_init.py index a3c83357e..a7b19a1ac 100644 --- a/tests/test_config/test_init.py +++ b/tests/test_config/test_init.py @@ -17,20 +17,29 @@ from pyramid.exceptions import ConfigurationConflictError from pyramid.interfaces import IRequest + class ConfiguratorTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config - def _getViewCallable(self, config, ctx_iface=None, request_iface=None, - name='', exception_view=False): + def _getViewCallable( + self, + config, + ctx_iface=None, + request_iface=None, + name='', + exception_view=False, + ): from zope.interface import Interface from pyramid.interfaces import IRequest from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier - if exception_view: # pragma: no cover + + if exception_view: # pragma: no cover classifier = IExceptionViewClassifier else: classifier = IViewClassifier @@ -39,16 +48,22 @@ class ConfiguratorTests(unittest.TestCase): if request_iface is None: request_iface = IRequest return config.registry.adapters.lookup( - (classifier, request_iface, ctx_iface), IView, name=name, - default=None) + (classifier, request_iface, ctx_iface), + IView, + name=name, + default=None, + ) def _registerEventListener(self, config, event_iface=None): - if event_iface is None: # pragma: no cover + if event_iface is None: # pragma: no cover from zope.interface import Interface + event_iface = Interface L = [] + def subscriber(*event): L.extend(event) + config.registry.registerHandler(subscriber, (event_iface,)) return L @@ -62,6 +77,7 @@ class ConfiguratorTests(unittest.TestCase): from pyramid.interfaces import ISettings from pyramid.config import Configurator from pyramid.interfaces import IRendererFactory + config = Configurator() this_pkg = sys.modules['tests.test_config'] self.assertTrue(config.registry.getUtility(ISettings)) @@ -72,27 +88,32 @@ class ConfiguratorTests(unittest.TestCase): def test_begin(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() config.manager = manager config.begin() - self.assertEqual(manager.pushed, - {'registry':config.registry, 'request':None}) + self.assertEqual( + manager.pushed, {'registry': config.registry, 'request': None} + ) self.assertEqual(manager.popped, False) def test_begin_with_request(self): from pyramid.config import Configurator + config = Configurator() request = object() manager = DummyThreadLocalManager() config.manager = manager config.begin(request=request) - self.assertEqual(manager.pushed, - {'registry':config.registry, 'request':request}) + self.assertEqual( + manager.pushed, {'registry': config.registry, 'request': request} + ) self.assertEqual(manager.popped, False) def test_begin_overrides_request(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() req = object() @@ -107,6 +128,7 @@ class ConfiguratorTests(unittest.TestCase): def test_begin_propagates_request_for_same_registry(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() req = object() @@ -120,6 +142,7 @@ class ConfiguratorTests(unittest.TestCase): def test_begin_does_not_propagate_request_for_diff_registry(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() req = object() @@ -133,6 +156,7 @@ class ConfiguratorTests(unittest.TestCase): def test_end(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() pushed = manager.pushed @@ -143,14 +167,16 @@ class ConfiguratorTests(unittest.TestCase): def test_context_manager(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() config.manager = manager view = lambda r: None with config as ctx: self.assertTrue(config is ctx) - self.assertEqual(manager.pushed, - {'registry': config.registry, 'request': None}) + self.assertEqual( + manager.pushed, {'registry': config.registry, 'request': None} + ) self.assertFalse(manager.popped) config.add_view(view) self.assertTrue(manager.popped) @@ -160,14 +186,15 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_with_package_registry(self): import sys from pyramid.config import Configurator + pkg = sys.modules['pyramid'] config = Configurator(package=pkg) self.assertEqual(config.package, pkg) def test_ctor_noreg_custom_settings(self): from pyramid.interfaces import ISettings - settings = {'reload_templates':True, - 'mysetting':True} + + settings = {'reload_templates': True, 'mysetting': True} config = self._makeOne(settings=settings) settings = config.registry.getUtility(ISettings) self.assertEqual(settings['reload_templates'], True) @@ -176,12 +203,14 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_noreg_debug_logger_None_default(self): from pyramid.interfaces import IDebugLogger + config = self._makeOne() logger = config.registry.getUtility(IDebugLogger) self.assertEqual(logger.name, 'tests.test_config') def test_ctor_noreg_debug_logger_non_None(self): from pyramid.interfaces import IDebugLogger + logger = object() config = self._makeOne(debug_logger=logger) result = config.registry.getUtility(IDebugLogger) @@ -189,6 +218,7 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_authentication_policy(self): from pyramid.interfaces import IAuthenticationPolicy + policy = object() config = self._makeOne(authentication_policy=policy) config.commit() @@ -202,6 +232,7 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_no_root_factory(self): from pyramid.interfaces import IRootFactory + config = self._makeOne() self.assertEqual(config.registry.queryUtility(IRootFactory), None) config.commit() @@ -209,6 +240,7 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_with_root_factory(self): from pyramid.interfaces import IRootFactory + factory = object() config = self._makeOne(root_factory=factory) self.assertEqual(config.registry.queryUtility(IRootFactory), None) @@ -217,27 +249,36 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_alternate_renderers(self): from pyramid.interfaces import IRendererFactory + renderer = object() config = self._makeOne(renderers=[('yeah', renderer)]) config.commit() - self.assertEqual(config.registry.getUtility(IRendererFactory, 'yeah'), - renderer) + self.assertEqual( + config.registry.getUtility(IRendererFactory, 'yeah'), renderer + ) def test_ctor_default_renderers(self): from pyramid.interfaces import IRendererFactory from pyramid.renderers import json_renderer_factory + config = self._makeOne() - self.assertEqual(config.registry.getUtility(IRendererFactory, 'json'), - json_renderer_factory) + self.assertEqual( + config.registry.getUtility(IRendererFactory, 'json'), + json_renderer_factory, + ) def test_ctor_default_permission(self): from pyramid.interfaces import IDefaultPermission + config = self._makeOne(default_permission='view') config.commit() - self.assertEqual(config.registry.getUtility(IDefaultPermission), 'view') + self.assertEqual( + config.registry.getUtility(IDefaultPermission), 'view' + ) def test_ctor_session_factory(self): from pyramid.interfaces import ISessionFactory + factory = object() config = self._makeOne(session_factory=factory) self.assertEqual(config.registry.queryUtility(ISessionFactory), None) @@ -246,39 +287,46 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_default_view_mapper(self): from pyramid.interfaces import IViewMapperFactory + mapper = object() config = self._makeOne(default_view_mapper=mapper) config.commit() - self.assertEqual(config.registry.getUtility(IViewMapperFactory), - mapper) + self.assertEqual( + config.registry.getUtility(IViewMapperFactory), mapper + ) def test_ctor_httpexception_view_default(self): from pyramid.interfaces import IExceptionResponse from pyramid.httpexceptions import default_exceptionresponse_view from pyramid.interfaces import IRequest + config = self._makeOne() - view = self._getViewCallable(config, - ctx_iface=IExceptionResponse, - request_iface=IRequest) + view = self._getViewCallable( + config, ctx_iface=IExceptionResponse, request_iface=IRequest + ) self.assertTrue(view.__wraps__ is default_exceptionresponse_view) def test_ctor_exceptionresponse_view_None(self): from pyramid.interfaces import IExceptionResponse from pyramid.interfaces import IRequest + config = self._makeOne(exceptionresponse_view=None) - view = self._getViewCallable(config, - ctx_iface=IExceptionResponse, - request_iface=IRequest) + view = self._getViewCallable( + config, ctx_iface=IExceptionResponse, request_iface=IRequest + ) self.assertTrue(view is None) def test_ctor_exceptionresponse_view_custom(self): from pyramid.interfaces import IExceptionResponse from pyramid.interfaces import IRequest - def exceptionresponse_view(context, request): pass + + def exceptionresponse_view(context, request): + pass + config = self._makeOne(exceptionresponse_view=exceptionresponse_view) - view = self._getViewCallable(config, - ctx_iface=IExceptionResponse, - request_iface=IRequest) + view = self._getViewCallable( + config, ctx_iface=IExceptionResponse, request_iface=IRequest + ) self.assertTrue(view.__wraps__ is exceptionresponse_view) def test_ctor_with_introspection(self): @@ -287,27 +335,33 @@ class ConfiguratorTests(unittest.TestCase): def test_ctor_default_webob_response_adapter_registered(self): from webob import Response as WebobResponse + response = WebobResponse() from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) result = config.registry.queryAdapter(response, IResponse) self.assertEqual(result, response) - + def test_with_package_module(self): from . import test_init + config = self._makeOne() newconfig = config.with_package(test_init) import tests.test_config + self.assertEqual(newconfig.package, tests.test_config) def test_with_package_package(self): from tests import test_config + config = self._makeOne() newconfig = config.with_package(test_config) self.assertEqual(newconfig.package, test_config) def test_with_package(self): import tests + config = self._makeOne() config.basepath = 'basepath' config.info = 'info' @@ -325,6 +379,7 @@ class ConfiguratorTests(unittest.TestCase): def test_maybe_dotted_string_success(self): import tests.test_config + config = self._makeOne() result = config.maybe_dotted('tests.test_config') self.assertEqual(result, tests.test_config) @@ -335,24 +390,28 @@ class ConfiguratorTests(unittest.TestCase): def test_maybe_dotted_notstring_success(self): import tests.test_config + config = self._makeOne() result = config.maybe_dotted(tests.test_config) self.assertEqual(result, tests.test_config) def test_absolute_asset_spec_already_absolute(self): import tests.test_config + config = self._makeOne(package=tests.test_config) result = config.absolute_asset_spec('already:absolute') self.assertEqual(result, 'already:absolute') def test_absolute_asset_spec_notastring(self): import tests.test_config + config = self._makeOne(package=tests.test_config) result = config.absolute_asset_spec(None) self.assertEqual(result, None) def test_absolute_asset_spec_relative(self): import tests.test_config + config = self._makeOne(package=tests.test_config) result = config.absolute_asset_spec('files') self.assertEqual(result, 'tests.test_config:files') @@ -373,13 +432,17 @@ class ConfiguratorTests(unittest.TestCase): def test__fix_registry_queryAdapterOrSelf(self): from zope.interface import Interface from zope.interface import implementer + class IFoo(Interface): pass + @implementer(IFoo) class Foo(object): pass + class Bar(object): pass + adaptation = () foo = Foo() bar = Bar() @@ -397,9 +460,16 @@ class ConfiguratorTests(unittest.TestCase): self.assertEqual(len(reg.adapters), 1) args, kw = reg.adapters[0] self.assertEqual(args[0]('abc'), 'abc') - self.assertEqual(kw, - {'info': '', 'provided': 'provided', - 'required': 'required', 'name': 'abc', 'event': True}) + self.assertEqual( + kw, + { + 'info': '', + 'provided': 'provided', + 'required': 'required', + 'name': 'abc', + 'event': True, + }, + ) def test__fix_registry_adds__lock(self): reg = DummyRegistry() @@ -428,6 +498,7 @@ class ConfiguratorTests(unittest.TestCase): from webob.exc import WSGIHTTPException from pyramid.interfaces import IExceptionResponse from pyramid.view import default_exceptionresponse_view + reg = DummyRegistry() config = self._makeOne(reg) views = [] @@ -435,17 +506,29 @@ class ConfiguratorTests(unittest.TestCase): config.add_default_view_predicates = lambda *arg: None config._add_tween = lambda *arg, **kw: False config.setup_registry() - self.assertEqual(views[0], ((default_exceptionresponse_view,), - {'context':IExceptionResponse})) - self.assertEqual(views[1], ((default_exceptionresponse_view,), - {'context':WSGIHTTPException})) + self.assertEqual( + views[0], + ( + (default_exceptionresponse_view,), + {'context': IExceptionResponse}, + ), + ) + self.assertEqual( + views[1], + ( + (default_exceptionresponse_view,), + {'context': WSGIHTTPException}, + ), + ) def test_setup_registry_registers_default_view_predicates(self): reg = DummyRegistry() config = self._makeOne(reg) vp_called = [] config.add_view = lambda *arg, **kw: None - config.add_default_view_predicates = lambda *arg: vp_called.append(True) + config.add_default_view_predicates = lambda *arg: vp_called.append( + True + ) config._add_tween = lambda *arg, **kw: False config.setup_registry() self.assertTrue(vp_called) @@ -453,11 +536,13 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_registers_default_webob_iresponse_adapter(self): from webob import Response from pyramid.interfaces import IResponse + config = self._makeOne() config.setup_registry() response = Response() self.assertTrue( - config.registry.queryAdapter(response, IResponse) is response) + config.registry.queryAdapter(response, IResponse) is response + ) def test_setup_registry_explicit_notfound_trumps_iexceptionresponse(self): from pyramid.renderers import null_renderer @@ -465,24 +550,29 @@ class ConfiguratorTests(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPNotFound from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg, autocommit=True) - config.setup_registry() # registers IExceptionResponse default view + config.setup_registry() # registers IExceptionResponse default view + def myview(context, request): return 'OK' + config.add_view(myview, context=HTTPNotFound, renderer=null_renderer) request = self._makeRequest(config) - view = self._getViewCallable(config, - ctx_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + ctx_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) result = view(None, request) self.assertEqual(result, 'OK') def test_setup_registry_custom_settings(self): from pyramid.registry import Registry from pyramid.interfaces import ISettings - settings = {'reload_templates':True, - 'mysetting':True} + + settings = {'reload_templates': True, 'mysetting': True} reg = Registry() config = self._makeOne(reg) config.setup_registry(settings=settings) @@ -494,6 +584,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_debug_logger_None_default(self): from pyramid.registry import Registry from pyramid.interfaces import IDebugLogger + reg = Registry() config = self._makeOne(reg) config.setup_registry() @@ -503,6 +594,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_debug_logger_non_None(self): from pyramid.registry import Registry from pyramid.interfaces import IDebugLogger + logger = object() reg = Registry() config = self._makeOne(reg) @@ -513,6 +605,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_debug_logger_name(self): from pyramid.registry import Registry from pyramid.interfaces import IDebugLogger + reg = Registry() config = self._makeOne(reg) config.setup_registry(debug_logger='foo') @@ -522,6 +615,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_authentication_policy(self): from pyramid.registry import Registry from pyramid.interfaces import IAuthenticationPolicy + policy = object() reg = Registry() config = self._makeOne(reg) @@ -533,29 +627,36 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_authentication_policy_dottedname(self): from pyramid.registry import Registry from pyramid.interfaces import IAuthenticationPolicy + reg = Registry() config = self._makeOne(reg) config.setup_registry(authentication_policy='tests.test_config') config.commit() result = reg.getUtility(IAuthenticationPolicy) import tests.test_config + self.assertEqual(result, tests.test_config) def test_setup_registry_authorization_policy_dottedname(self): from pyramid.registry import Registry from pyramid.interfaces import IAuthorizationPolicy + reg = Registry() config = self._makeOne(reg) dummy = object() - config.setup_registry(authentication_policy=dummy, - authorization_policy='tests.test_config') + config.setup_registry( + authentication_policy=dummy, + authorization_policy='tests.test_config', + ) config.commit() result = reg.getUtility(IAuthorizationPolicy) import tests.test_config + self.assertEqual(result, tests.test_config) def test_setup_registry_authorization_policy_only(self): from pyramid.registry import Registry + policy = object() reg = Registry() config = self._makeOne(reg) @@ -565,6 +666,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_no_default_root_factory(self): from pyramid.registry import Registry from pyramid.interfaces import IRootFactory + reg = Registry() config = self._makeOne(reg) config.setup_registry() @@ -574,9 +676,11 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_dottedname_root_factory(self): from pyramid.registry import Registry from pyramid.interfaces import IRootFactory + reg = Registry() config = self._makeOne(reg) import tests.test_config + config.setup_registry(root_factory='tests.test_config') self.assertEqual(reg.queryUtility(IRootFactory), None) config.commit() @@ -585,9 +689,11 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_locale_negotiator_dottedname(self): from pyramid.registry import Registry from pyramid.interfaces import ILocaleNegotiator + reg = Registry() config = self._makeOne(reg) import tests.test_config + config.setup_registry(locale_negotiator='tests.test_config') self.assertEqual(reg.queryUtility(ILocaleNegotiator), None) config.commit() @@ -597,6 +703,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_locale_negotiator(self): from pyramid.registry import Registry from pyramid.interfaces import ILocaleNegotiator + reg = Registry() config = self._makeOne(reg) negotiator = object() @@ -609,6 +716,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_request_factory(self): from pyramid.registry import Registry from pyramid.interfaces import IRequestFactory + reg = Registry() config = self._makeOne(reg) factory = object() @@ -621,6 +729,7 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_response_factory(self): from pyramid.registry import Registry from pyramid.interfaces import IResponseFactory + reg = Registry() config = self._makeOne(reg) factory = lambda r: object() @@ -633,9 +742,11 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_request_factory_dottedname(self): from pyramid.registry import Registry from pyramid.interfaces import IRequestFactory + reg = Registry() config = self._makeOne(reg) import tests.test_config + config.setup_registry(request_factory='tests.test_config') self.assertEqual(reg.queryUtility(IRequestFactory), None) config.commit() @@ -645,17 +756,18 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_alternate_renderers(self): from pyramid.registry import Registry from pyramid.interfaces import IRendererFactory + renderer = object() reg = Registry() config = self._makeOne(reg) config.setup_registry(renderers=[('yeah', renderer)]) config.commit() - self.assertEqual(reg.getUtility(IRendererFactory, 'yeah'), - renderer) + self.assertEqual(reg.getUtility(IRendererFactory, 'yeah'), renderer) def test_setup_registry_default_permission(self): from pyramid.registry import Registry from pyramid.interfaces import IDefaultPermission + reg = Registry() config = self._makeOne(reg) config.setup_registry(default_permission='view') @@ -664,12 +776,12 @@ class ConfiguratorTests(unittest.TestCase): def test_setup_registry_includes(self): from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg) settings = { - 'pyramid.includes': -"""tests.test_config.dummy_include -tests.test_config.dummy_include2""", + 'pyramid.includes': """tests.test_config.dummy_include +tests.test_config.dummy_include2""" } config.setup_registry(settings=settings) self.assertTrue(reg.included) @@ -677,11 +789,11 @@ tests.test_config.dummy_include2""", def test_setup_registry_includes_spaces(self): from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg) settings = { - 'pyramid.includes': -"""tests.test_config.dummy_include tests.test_config.dummy_include2""", + 'pyramid.includes': """tests.test_config.dummy_include tests.test_config.dummy_include2""" } config.setup_registry(settings=settings) self.assertTrue(reg.included) @@ -690,19 +802,17 @@ tests.test_config.dummy_include2""", def test_setup_registry_tweens(self): from pyramid.interfaces import ITweens from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg) - settings = { - 'pyramid.tweens': - 'tests.test_config.dummy_tween_factory' - } + settings = {'pyramid.tweens': 'tests.test_config.dummy_tween_factory'} config.setup_registry(settings=settings) config.commit() tweens = config.registry.getUtility(ITweens) self.assertEqual( tweens.explicit, - [('tests.test_config.dummy_tween_factory', - dummy_tween_factory)]) + [('tests.test_config.dummy_tween_factory', dummy_tween_factory)], + ) def test_introspector_decorator(self): inst = self._makeOne() @@ -723,6 +833,7 @@ tests.test_config.dummy_include2""", import pyramid.config from pyramid.router import Router from pyramid.interfaces import IApplicationCreated + manager = DummyThreadLocalManager() config = self._makeOne() subscriber = self._registerEventListener(config, IApplicationCreated) @@ -739,6 +850,7 @@ tests.test_config.dummy_include2""", def test_include_with_dotted_name(self): from tests import test_config + config = self._makeOne() config.include('tests.test_config.dummy_include') after = config.action_state @@ -751,6 +863,7 @@ tests.test_config.dummy_include2""", def test_include_with_python_callable(self): from tests import test_config + config = self._makeOne() config.include(dummy_include) after = config.action_state @@ -763,6 +876,7 @@ tests.test_config.dummy_include2""", def test_include_with_module_defaults_to_includeme(self): from tests import test_config + config = self._makeOne() config.include('tests.test_config') after = config.action_state @@ -775,24 +889,31 @@ tests.test_config.dummy_include2""", def test_include_with_module_defaults_to_includeme_missing(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() self.assertRaises(ConfigurationError, config.include, 'tests') def test_include_with_route_prefix(self): root_config = self._makeOne(autocommit=True) + def dummy_subapp(config): self.assertEqual(config.route_prefix, 'root') + root_config.include(dummy_subapp, route_prefix='root') def test_include_with_nested_route_prefix(self): root_config = self._makeOne(autocommit=True, route_prefix='root') + def dummy_subapp2(config): self.assertEqual(config.route_prefix, 'root/nested') + def dummy_subapp3(config): self.assertEqual(config.route_prefix, 'root/nested/nested2') config.include(dummy_subapp4) + def dummy_subapp4(config): self.assertEqual(config.route_prefix, 'root/nested/nested2') + def dummy_subapp(config): self.assertEqual(config.route_prefix, 'root/nested') config.include(dummy_subapp2) @@ -803,31 +924,39 @@ tests.test_config.dummy_include2""", def test_include_with_missing_source_file(self): from pyramid.exceptions import ConfigurationError import inspect + config = self._makeOne() + class DummyInspect(object): def getmodule(self, c): return inspect.getmodule(c) + def getsourcefile(self, c): return None + config.inspect = DummyInspect() try: config.include('tests.test_config.dummy_include') except ConfigurationError as e: self.assertEqual( - e.args[0], + e.args[0], "No source file for module 'tests.test_config' (.py " - "file must exist, refusing to use orphan .pyc or .pyo file).") - else: # pragma: no cover + "file must exist, refusing to use orphan .pyc or .pyo file).", + ) + else: # pragma: no cover raise AssertionError def test_include_constant_root_package(self): import tests from tests import test_config + config = self._makeOne(root_package=tests) results = {} + def include(config): results['package'] = config.package results['root_package'] = config.root_package + config.include(include) self.assertEqual(results['root_package'], tests) self.assertEqual(results['package'], test_config) @@ -835,9 +964,12 @@ tests.test_config.dummy_include2""", def test_include_threadlocals_active(self): from pyramid.threadlocal import get_current_registry from tests import test_config + stack = [] + def include(config): stack.append(get_current_registry()) + config = self._makeOne() config.include(include) self.assertTrue(stack[0] is config.registry) @@ -848,10 +980,11 @@ tests.test_config.dummy_include2""", def test_action_branching_kw_is_not_None(self): config = self._makeOne(autocommit=True) - self.assertEqual(config.action('discrim', kw={'a':1}), None) + self.assertEqual(config.action('discrim', kw={'a': 1}), None) def test_action_autocommit_with_introspectables(self): from pyramid.config.util import ActionInfo + config = self._makeOne(autocommit=True) intr = DummyIntrospectable() config.action('discrim', introspectables=(intr,)) @@ -865,25 +998,32 @@ tests.test_config.dummy_include2""", intr = DummyIntrospectable() config.action('discrim', introspectables=(intr,)) self.assertEqual(len(intr.registered), 0) - + def test_action_branching_nonautocommit_with_config_info(self): config = self._makeOne(autocommit=False) config.info = 'abc' state = DummyActionState() state.autocommit = False config.action_state = state - config.action('discrim', kw={'a':1}) + config.action('discrim', kw={'a': 1}) self.assertEqual( state.actions, - [((), - {'args': (), - 'callable': None, - 'discriminator': 'discrim', - 'includepath': (), - 'info': 'abc', - 'introspectables': (), - 'kw': {'a': 1}, - 'order': 0})]) + [ + ( + (), + { + 'args': (), + 'callable': None, + 'discriminator': 'discrim', + 'includepath': (), + 'info': 'abc', + 'introspectables': (), + 'kw': {'a': 1}, + 'order': 0, + }, + ) + ], + ) def test_action_branching_nonautocommit_without_config_info(self): config = self._makeOne(autocommit=False) @@ -892,18 +1032,25 @@ tests.test_config.dummy_include2""", state = DummyActionState() config.action_state = state state.autocommit = False - config.action('discrim', kw={'a':1}) + config.action('discrim', kw={'a': 1}) self.assertEqual( state.actions, - [((), - {'args': (), - 'callable': None, - 'discriminator': 'discrim', - 'includepath': (), - 'info': 'z', - 'introspectables': (), - 'kw': {'a': 1}, - 'order': 0})]) + [ + ( + (), + { + 'args': (), + 'callable': None, + 'discriminator': 'discrim', + 'includepath': (), + 'info': 'z', + 'introspectables': (), + 'kw': {'a': 1}, + 'order': 0, + }, + ) + ], + ) def test_action_branching_nonautocommit_with_introspectables(self): config = self._makeOne(autocommit=False) @@ -914,8 +1061,7 @@ tests.test_config.dummy_include2""", state.autocommit = False intr = DummyIntrospectable() config.action('discrim', introspectables=(intr,)) - self.assertEqual( - state.actions[0][1]['introspectables'], (intr,)) + self.assertEqual(state.actions[0][1]['introspectables'], (intr,)) def test_action_nonautocommit_with_introspectables_introspection_off(self): config = self._makeOne(autocommit=False) @@ -927,14 +1073,14 @@ tests.test_config.dummy_include2""", state.autocommit = False intr = DummyIntrospectable() config.action('discrim', introspectables=(intr,)) - self.assertEqual( - state.actions[0][1]['introspectables'], ()) - + self.assertEqual(state.actions[0][1]['introspectables'], ()) + def test_scan_integration(self): from zope.interface import alsoProvides from pyramid.interfaces import IRequest from pyramid.view import render_view_to_response import tests.test_config.pkgs.scannable as package + config = self._makeOne(autocommit=True) config.scan(package) @@ -951,13 +1097,13 @@ tests.test_config.dummy_include2""", result = render_view_to_response(ctx, req, '') self.assertEqual(result, 'grokked_post') - result= render_view_to_response(ctx, req, 'grokked_class') + result = render_view_to_response(ctx, req, 'grokked_class') self.assertEqual(result, 'grokked_class') - result= render_view_to_response(ctx, req, 'grokked_instance') + result = render_view_to_response(ctx, req, 'grokked_instance') self.assertEqual(result, 'grokked_instance') - result= render_view_to_response(ctx, req, 'oldstyle_grokked_class') + result = render_view_to_response(ctx, req, 'oldstyle_grokked_class') self.assertEqual(result, 'oldstyle_grokked_class') req.method = 'GET' @@ -968,14 +1114,15 @@ tests.test_config.dummy_include2""", result = render_view_to_response(ctx, req, 'another') self.assertEqual(result, 'another_grokked_post') - result= render_view_to_response(ctx, req, 'another_grokked_class') + result = render_view_to_response(ctx, req, 'another_grokked_class') self.assertEqual(result, 'another_grokked_class') - result= render_view_to_response(ctx, req, 'another_grokked_instance') + result = render_view_to_response(ctx, req, 'another_grokked_instance') self.assertEqual(result, 'another_grokked_instance') - result= render_view_to_response(ctx, req, - 'another_oldstyle_grokked_class') + result = render_view_to_response( + ctx, req, 'another_oldstyle_grokked_class' + ) self.assertEqual(result, 'another_oldstyle_grokked_class') result = render_view_to_response(ctx, req, 'stacked1') @@ -1007,8 +1154,9 @@ tests.test_config.dummy_include2""", # assertion may fail there. We don't support Jython at the moment, # this is just a note to a future self. - self.assertRaises(TypeError, - render_view_to_response, ctx, req, 'basemethod') + self.assertRaises( + TypeError, render_view_to_response, ctx, req, 'basemethod' + ) result = render_view_to_response(ctx, req, 'method1') self.assertEqual(result, 'method1') @@ -1039,9 +1187,9 @@ tests.test_config.dummy_include2""", from pyramid.interfaces import IRequest from pyramid.view import render_view_to_response import tests.test_config.pkgs.scannable as package + config = self._makeOne(autocommit=True) - config.scan(package, - ignore='tests.test_config.pkgs.scannable.another') + config.scan(package, ignore='tests.test_config.pkgs.scannable.another') ctx = DummyContext() req = DummyRequest() @@ -1055,11 +1203,12 @@ tests.test_config.dummy_include2""", # ignored v = render_view_to_response(ctx, req, 'another_stacked_class2') self.assertEqual(v, None) - + def test_scan_integration_dottedname_package(self): from zope.interface import alsoProvides from pyramid.interfaces import IRequest from pyramid.view import render_view_to_response + config = self._makeOne(autocommit=True) config.scan('tests.test_config.pkgs.scannable') @@ -1081,45 +1230,56 @@ tests.test_config.dummy_include2""", # fancy sys.path manipulation here to appease "setup.py test" which # fails miserably when it can't import something in the package import sys + try: here = os.path.dirname(__file__) path = os.path.join(here, 'path') sys.path.append(path) config = self._makeOne(autocommit=True) + class FooException(Exception): pass + def onerror(name): raise FooException - self.assertRaises(FooException, config.scan, 'scanerror', - onerror=onerror) + + self.assertRaises( + FooException, config.scan, 'scanerror', onerror=onerror + ) finally: sys.path.remove(path) def test_scan_integration_conflict(self): from tests.test_config.pkgs import selfscan from pyramid.config import Configurator + c = Configurator() c.scan(selfscan) c.scan(selfscan) try: c.commit() except ConfigurationConflictError as why: + def scanconflicts(e): conflicts = e._conflicts.values() for conflict in conflicts: for confinst in conflict: yield confinst.src + which = list(scanconflicts(why)) self.assertEqual(len(which), 4) self.assertTrue("@view_config(renderer='string')" in which) - self.assertTrue("@view_config(name='two', renderer='string')" in - which) + self.assertTrue( + "@view_config(name='two', renderer='string')" in which + ) @skip_on('py3') def test_hook_zca(self): from zope.component import getSiteManager + def foo(): '123' + try: config = self._makeOne() config.hook_zca() @@ -1132,8 +1292,10 @@ tests.test_config.dummy_include2""", @skip_on('py3') def test_unhook_zca(self): from zope.component import getSiteManager + def foo(): '123' + try: getSiteManager.sethook(foo) config = self._makeOne() @@ -1145,18 +1307,29 @@ tests.test_config.dummy_include2""", def test_commit_conflict_simple(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass + + def view1(request): + pass + + def view2(request): + pass + config.add_view(view1) config.add_view(view2) self.assertRaises(ConfigurationConflictError, config.commit) def test_commit_conflict_resolved_with_include(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass + + def view1(request): + pass + + def view2(request): + pass + def includeme(config): config.add_view(view2) + config.add_view(view1) config.include(includeme) config.commit() @@ -1165,12 +1338,19 @@ tests.test_config.dummy_include2""", def test_commit_conflict_with_two_includes(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass + + def view1(request): + pass + + def view2(request): + pass + def includeme1(config): config.add_view(view1) + def includeme2(config): config.add_view(view2) + config.include(includeme1) config.include(includeme2) try: @@ -1179,18 +1359,27 @@ tests.test_config.dummy_include2""", c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'includeme1') self.assertEqual(c2, 'includeme2') - else: #pragma: no cover + else: # pragma: no cover raise AssertionError def test_commit_conflict_resolved_with_two_includes_and_local(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass - def view3(request): pass + + def view1(request): + pass + + def view2(request): + pass + + def view3(request): + pass + def includeme1(config): config.add_view(view1) + def includeme2(config): config.add_view(view2) + config.include(includeme1) config.include(includeme2) config.add_view(view3) @@ -1200,10 +1389,18 @@ tests.test_config.dummy_include2""", def test_autocommit_no_conflicts(self): from pyramid.renderers import null_renderer + config = self._makeOne(autocommit=True) - def view1(request): pass - def view2(request): pass - def view3(request): pass + + def view1(request): + pass + + def view2(request): + pass + + def view3(request): + pass + config.add_view(view1, renderer=null_renderer) config.add_view(view2, renderer=null_renderer) config.add_view(view3, renderer=null_renderer) @@ -1213,8 +1410,13 @@ tests.test_config.dummy_include2""", def test_conflict_set_notfound_view(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass + + def view1(request): + pass + + def view2(request): + pass + config.set_notfound_view(view1) config.set_notfound_view(view2) try: @@ -1223,13 +1425,18 @@ tests.test_config.dummy_include2""", c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'test_conflict_set_notfound_view') self.assertEqual(c2, 'test_conflict_set_notfound_view') - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_conflict_set_forbidden_view(self): config = self._makeOne() - def view1(request): pass - def view2(request): pass + + def view1(request): + pass + + def view2(request): + pass + config.set_forbidden_view(view1) config.set_forbidden_view(view2) try: @@ -1238,7 +1445,7 @@ tests.test_config.dummy_include2""", c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'test_conflict_set_forbidden_view') self.assertEqual(c2, 'test_conflict_set_forbidden_view') - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test___getattr__missing_when_directives_exist(self): @@ -1253,31 +1460,38 @@ tests.test_config.dummy_include2""", def test___getattr__matches(self): config = self._makeOne() - def foo(config): pass - directives = {'foo':(foo, True)} + + def foo(config): + pass + + directives = {'foo': (foo, True)} config.registry._directives = directives foo_meth = config.foo self.assertTrue(getattr(foo_meth, im_func).__docobj__ is foo) def test___getattr__matches_no_action_wrap(self): config = self._makeOne() - def foo(config): pass - directives = {'foo':(foo, False)} + + def foo(config): + pass + + directives = {'foo': (foo, False)} config.registry._directives = directives foo_meth = config.foo self.assertTrue(getattr(foo_meth, im_func) is foo) -class TestConfigurator_add_directive(unittest.TestCase): +class TestConfigurator_add_directive(unittest.TestCase): def setUp(self): from pyramid.config import Configurator + self.config = Configurator() def test_extend_with_dotted_name(self): from tests import test_config + config = self.config - config.add_directive( - 'dummy_extend', 'tests.test_config.dummy_extend') + config.add_directive('dummy_extend', 'tests.test_config.dummy_extend') self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state @@ -1288,9 +1502,11 @@ class TestConfigurator_add_directive(unittest.TestCase): def test_add_directive_with_partial(self): from tests import test_config + config = self.config config.add_directive( - 'dummy_partial', 'tests.test_config.dummy_partial') + 'dummy_partial', 'tests.test_config.dummy_partial' + ) self.assertTrue(hasattr(config, 'dummy_partial')) config.dummy_partial() after = config.action_state @@ -1301,9 +1517,11 @@ class TestConfigurator_add_directive(unittest.TestCase): def test_add_directive_with_custom_callable(self): from tests import test_config + config = self.config config.add_directive( - 'dummy_callable', 'tests.test_config.dummy_callable') + 'dummy_callable', 'tests.test_config.dummy_callable' + ) self.assertTrue(hasattr(config, 'dummy_callable')) config.dummy_callable('discrim') after = config.action_state @@ -1314,9 +1532,9 @@ class TestConfigurator_add_directive(unittest.TestCase): def test_extend_with_python_callable(self): from tests import test_config + config = self.config - config.add_directive( - 'dummy_extend', dummy_extend) + config.add_directive('dummy_extend', dummy_extend) self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state @@ -1327,10 +1545,8 @@ class TestConfigurator_add_directive(unittest.TestCase): def test_extend_same_name_doesnt_conflict(self): config = self.config - config.add_directive( - 'dummy_extend', dummy_extend) - config.add_directive( - 'dummy_extend', dummy_extend2) + config.add_directive('dummy_extend', dummy_extend) + config.add_directive('dummy_extend', dummy_extend2) self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state @@ -1341,8 +1557,7 @@ class TestConfigurator_add_directive(unittest.TestCase): def test_extend_action_method_successful(self): config = self.config - config.add_directive( - 'dummy_extend', dummy_extend) + config.add_directive('dummy_extend', dummy_extend) config.dummy_extend('discrim') config.dummy_extend('discrim') self.assertRaises(ConfigurationConflictError, config.commit) @@ -1360,16 +1575,25 @@ class TestConfigurator_add_directive(unittest.TestCase): self.assertEqual(action['callable'], None) self.assertEqual(action['args'], config2.package) + class TestConfigurator__add_predicate(unittest.TestCase): def _makeOne(self): from pyramid.config import Configurator + return Configurator() def test_factory_as_object(self): config = self._makeOne() - def _fakeAction(discriminator, callable=None, args=(), kw=None, - order=0, introspectables=(), **extra): + def _fakeAction( + discriminator, + callable=None, + args=(), + kw=None, + order=0, + introspectables=(), + **extra + ): self.assertEqual(len(introspectables), 1) self.assertEqual(introspectables[0]['name'], 'testing') self.assertEqual(introspectables[0]['factory'], DummyPredicate) @@ -1380,63 +1604,82 @@ class TestConfigurator__add_predicate(unittest.TestCase): def test_factory_as_dotted_name(self): config = self._makeOne() - def _fakeAction(discriminator, callable=None, args=(), - kw=None, order=0, introspectables=(), **extra): + def _fakeAction( + discriminator, + callable=None, + args=(), + kw=None, + order=0, + introspectables=(), + **extra + ): self.assertEqual(len(introspectables), 1) self.assertEqual(introspectables[0]['name'], 'testing') self.assertEqual(introspectables[0]['factory'], DummyPredicate) config.action = _fakeAction config._add_predicate( - 'route', - 'testing', - 'tests.test_config.test_init.DummyPredicate' - ) - + 'route', 'testing', 'tests.test_config.test_init.DummyPredicate' + ) + + class TestActionState(unittest.TestCase): def _makeOne(self): from pyramid.config import ActionState + return ActionState() - + def test_it(self): c = self._makeOne() self.assertEqual(c.actions, []) def test_action_simple(self): from . import dummyfactory as f + c = self._makeOne() c.actions = [] - c.action(1, f, (1,), {'x':1}) + c.action(1, f, (1,), {'x': 1}) self.assertEqual( c.actions, - [{'args': (1,), - 'callable': f, - 'discriminator': 1, - 'includepath': (), - 'info': None, - 'introspectables': (), - 'kw': {'x': 1}, - 'order': 0}]) + [ + { + 'args': (1,), + 'callable': f, + 'discriminator': 1, + 'includepath': (), + 'info': None, + 'introspectables': (), + 'kw': {'x': 1}, + 'order': 0, + } + ], + ) c.action(None) self.assertEqual( c.actions, - [{'args': (1,), - 'callable': f, - 'discriminator': 1, - 'includepath': (), - 'info': None, - 'introspectables': (), - 'kw': {'x': 1}, - 'order': 0}, - - {'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': (), - 'info': None, - 'introspectables': (), - 'kw': {}, - 'order': 0},]) + [ + { + 'args': (1,), + 'callable': f, + 'discriminator': 1, + 'includepath': (), + 'info': None, + 'introspectables': (), + 'kw': {'x': 1}, + 'order': 0, + }, + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': (), + 'info': None, + 'introspectables': (), + 'kw': {}, + 'order': 0, + }, + ], + ) def test_action_with_includepath(self): c = self._makeOne() @@ -1444,42 +1687,57 @@ class TestActionState(unittest.TestCase): c.action(None, includepath=('abc',)) self.assertEqual( c.actions, - [{'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': ('abc',), - 'info': None, - 'introspectables': (), - 'kw': {}, - 'order': 0}]) + [ + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': ('abc',), + 'info': None, + 'introspectables': (), + 'kw': {}, + 'order': 0, + } + ], + ) def test_action_with_info(self): c = self._makeOne() c.action(None, info='abc') self.assertEqual( c.actions, - [{'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': (), - 'info': 'abc', - 'introspectables': (), - 'kw': {}, - 'order': 0}]) + [ + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': (), + 'info': 'abc', + 'introspectables': (), + 'kw': {}, + 'order': 0, + } + ], + ) def test_action_with_includepath_and_info(self): c = self._makeOne() c.action(None, includepath=('spec',), info='bleh') self.assertEqual( c.actions, - [{'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': ('spec',), - 'info': 'bleh', - 'introspectables': (), - 'kw': {}, - 'order': 0}]) + [ + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': ('spec',), + 'info': 'bleh', + 'introspectables': (), + 'kw': {}, + 'order': 0, + } + ], + ) def test_action_with_order(self): c = self._makeOne() @@ -1487,14 +1745,19 @@ class TestActionState(unittest.TestCase): c.action(None, order=99999) self.assertEqual( c.actions, - [{'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': (), - 'info': None, - 'introspectables': (), - 'kw': {}, - 'order': 99999}]) + [ + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': (), + 'info': None, + 'introspectables': (), + 'kw': {}, + 'order': 99999, + } + ], + ) def test_action_with_introspectables(self): c = self._makeOne() @@ -1503,14 +1766,19 @@ class TestActionState(unittest.TestCase): c.action(None, introspectables=(intr,)) self.assertEqual( c.actions, - [{'args': (), - 'callable': None, - 'discriminator': None, - 'includepath': (), - 'info': None, - 'introspectables': (intr,), - 'kw': {}, - 'order': 0}]) + [ + { + 'args': (), + 'callable': None, + 'discriminator': None, + 'includepath': (), + 'info': None, + 'introspectables': (intr,), + 'kw': {}, + 'order': 0, + } + ], + ) def test_processSpec(self): c = self._makeOne() @@ -1519,190 +1787,269 @@ class TestActionState(unittest.TestCase): def test_execute_actions_tuples(self): output = [] + def f(*a, **k): output.append((a, k)) + c = self._makeOne() c.actions = [ (1, f, (1,)), - (1, f, (11,), {}, ('x', )), + (1, f, (11,), {}, ('x',)), (2, f, (2,)), (None, None), - ] + ] c.execute_actions() - self.assertEqual(output, [((1,), {}), ((2,), {})]) + self.assertEqual(output, [((1,), {}), ((2,), {})]) def test_execute_actions_dicts(self): output = [] + def f(*a, **k): output.append((a, k)) + c = self._makeOne() c.actions = [ - {'discriminator':1, 'callable':f, 'args':(1,), 'kw':{}, - 'order':0, 'includepath':(), 'info':None, - 'introspectables':()}, - {'discriminator':1, 'callable':f, 'args':(11,), 'kw':{}, - 'includepath':('x',), 'order': 0, 'info':None, - 'introspectables':()}, - {'discriminator':2, 'callable':f, 'args':(2,), 'kw':{}, - 'order':0, 'includepath':(), 'info':None, - 'introspectables':()}, - {'discriminator':None, 'callable':None, 'args':(), 'kw':{}, - 'order':0, 'includepath':(), 'info':None, - 'introspectables':()}, - ] + { + 'discriminator': 1, + 'callable': f, + 'args': (1,), + 'kw': {}, + 'order': 0, + 'includepath': (), + 'info': None, + 'introspectables': (), + }, + { + 'discriminator': 1, + 'callable': f, + 'args': (11,), + 'kw': {}, + 'includepath': ('x',), + 'order': 0, + 'info': None, + 'introspectables': (), + }, + { + 'discriminator': 2, + 'callable': f, + 'args': (2,), + 'kw': {}, + 'order': 0, + 'includepath': (), + 'info': None, + 'introspectables': (), + }, + { + 'discriminator': None, + 'callable': None, + 'args': (), + 'kw': {}, + 'order': 0, + 'includepath': (), + 'info': None, + 'introspectables': (), + }, + ] c.execute_actions() - self.assertEqual(output, [((1,), {}), ((2,), {})]) + self.assertEqual(output, [((1,), {}), ((2,), {})]) def test_execute_actions_with_introspectables(self): output = [] + def f(*a, **k): output.append((a, k)) + c = self._makeOne() intr = DummyIntrospectable() c.actions = [ - {'discriminator':1, 'callable':f, 'args':(1,), 'kw':{}, - 'order':0, 'includepath':(), 'info':None, - 'introspectables':(intr,)}, - ] + { + 'discriminator': 1, + 'callable': f, + 'args': (1,), + 'kw': {}, + 'order': 0, + 'includepath': (), + 'info': None, + 'introspectables': (intr,), + } + ] introspector = object() c.execute_actions(introspector=introspector) - self.assertEqual(output, [((1,), {})]) + self.assertEqual(output, [((1,), {})]) self.assertEqual(intr.registered, [(introspector, None)]) def test_execute_actions_with_introspectable_no_callable(self): c = self._makeOne() intr = DummyIntrospectable() c.actions = [ - {'discriminator':1, 'callable':None, 'args':(1,), 'kw':{}, - 'order':0, 'includepath':(), 'info':None, - 'introspectables':(intr,)}, - ] + { + 'discriminator': 1, + 'callable': None, + 'args': (1,), + 'kw': {}, + 'order': 0, + 'includepath': (), + 'info': None, + 'introspectables': (intr,), + } + ] introspector = object() c.execute_actions(introspector=introspector) self.assertEqual(intr.registered, [(introspector, None)]) def test_execute_actions_error(self): output = [] + def f(*a, **k): output.append(('f', a, k)) + def bad(): raise NotImplementedError + c = self._makeOne() c.actions = [ (1, f, (1,)), - (1, f, (11,), {}, ('x', )), + (1, f, (11,), {}, ('x',)), (2, f, (2,)), - (3, bad, (), {}, (), 'oops') - ] + (3, bad, (), {}, (), 'oops'), + ] self.assertRaises(ConfigurationExecutionError, c.execute_actions) self.assertEqual(output, [('f', (1,), {}), ('f', (2,), {})]) def test_reentrant_action(self): output = [] c = self._makeOne() + def f(*a, **k): output.append(('f', a, k)) c.actions.append((3, g, (8,), {})) + def g(*a, **k): output.append(('g', a, k)) - c.actions = [ - (1, f, (1,)), - ] + + c.actions = [(1, f, (1,))] c.execute_actions() self.assertEqual(output, [('f', (1,), {}), ('g', (8,), {})]) def test_reentrant_action_with_deferred_discriminator(self): # see https://github.com/Pylons/pyramid/issues/2697 from pyramid.registry import Deferred + output = [] c = self._makeOne() + def f(*a, **k): output.append(('f', a, k)) c.actions.append((4, g, (4,), {}, (), None, 2)) + def g(*a, **k): output.append(('g', a, k)) + def h(*a, **k): output.append(('h', a, k)) + def discrim(): self.assertEqual(output, [('f', (1,), {}), ('g', (2,), {})]) return 3 + d = Deferred(discrim) c.actions = [ - (d, h, (3,), {}, (), None, 1), # order 1 - (1, f, (1,)), # order 0 - (2, g, (2,)), # order 0 + (d, h, (3,), {}, (), None, 1), # order 1 + (1, f, (1,)), # order 0 + (2, g, (2,)), # order 0 ] c.execute_actions() - self.assertEqual(output, [ - ('f', (1,), {}), ('g', (2,), {}), ('h', (3,), {}), ('g', (4,), {})]) + self.assertEqual( + output, + [ + ('f', (1,), {}), + ('g', (2,), {}), + ('h', (3,), {}), + ('g', (4,), {}), + ], + ) def test_reentrant_action_error(self): from pyramid.exceptions import ConfigurationError + c = self._makeOne() + def f(*a, **k): c.actions.append((3, g, (8,), {}, (), None, -1)) - def g(*a, **k): pass - c.actions = [ - (1, f, (1,)), - ] + + def g(*a, **k): + pass + + c.actions = [(1, f, (1,))] self.assertRaises(ConfigurationError, c.execute_actions) def test_reentrant_action_without_clear(self): c = self._makeOne() + def f(*a, **k): c.actions.append((3, g, (8,))) - def g(*a, **k): pass - c.actions = [ - (1, f, (1,)), - ] + + def g(*a, **k): + pass + + c.actions = [(1, f, (1,))] c.execute_actions(clear=False) - self.assertEqual(c.actions, [ - (1, f, (1,)), - (3, g, (8,)), - ]) + self.assertEqual(c.actions, [(1, f, (1,)), (3, g, (8,))]) def test_executing_conflicting_action_across_orders(self): from pyramid.exceptions import ConfigurationConflictError + c = self._makeOne() - def f(*a, **k): pass - def g(*a, **k): pass - c.actions = [ - (1, f, (1,), {}, (), None, -1), - (1, g, (2,)), - ] + + def f(*a, **k): + pass + + def g(*a, **k): + pass + + c.actions = [(1, f, (1,), {}, (), None, -1), (1, g, (2,))] self.assertRaises(ConfigurationConflictError, c.execute_actions) def test_executing_conflicting_action_across_reentrant_orders(self): from pyramid.exceptions import ConfigurationConflictError + c = self._makeOne() + def f(*a, **k): c.actions.append((1, g, (8,))) - def g(*a, **k): pass - c.actions = [ - (1, f, (1,), {}, (), None, -1), - ] + + def g(*a, **k): + pass + + c.actions = [(1, f, (1,), {}, (), None, -1)] self.assertRaises(ConfigurationConflictError, c.execute_actions) + class Test_reentrant_action_functional(unittest.TestCase): def _makeConfigurator(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_functional(self): def add_auto_route(config, name, view): - def register(): - config.add_view(route_name=name, view=view) - config.add_route(name, '/' + name) - config.action( - ('auto route', name), register, order=-30 - ) + def register(): + config.add_view(route_name=name, view=view) + config.add_route(name, '/' + name) + + config.action(('auto route', name), register, order=-30) + config = self._makeConfigurator() config.add_directive('add_auto_route', add_auto_route) - def my_view(request): return request.response + + def my_view(request): + return request.response + config.add_auto_route('foo', my_view) config.commit() from pyramid.interfaces import IRoutesMapper + mapper = config.registry.getUtility(IRoutesMapper) routes = mapper.get_routes() route = routes[0] @@ -1713,291 +2060,352 @@ class Test_reentrant_action_functional(unittest.TestCase): def test_deferred_discriminator(self): # see https://github.com/Pylons/pyramid/issues/2697 from pyramid.config import PHASE0_CONFIG + config = self._makeConfigurator() - def deriver(view, info): return view + + def deriver(view, info): + return view + deriver.options = ('foo',) config.add_view_deriver(deriver, 'foo_view') # add_view uses a deferred discriminator and will fail if executed # prior to add_view_deriver executing its action config.add_view(lambda r: r.response, name='', foo=1) + def dummy_action(): # trigger a re-entrant action config.action(None, lambda: None) + config.action(None, dummy_action, order=PHASE0_CONFIG) config.commit() + class Test_resolveConflicts(unittest.TestCase): def _callFUT(self, actions): from pyramid.config import resolveConflicts + return resolveConflicts(actions) def test_it_success_tuples(self): from . import dummyfactory as f - result = self._callFUT([ - (None, f), - (1, f, (1,), {}, (), 'first'), - (1, f, (2,), {}, ('x',), 'second'), - (1, f, (3,), {}, ('y',), 'third'), - (4, f, (4,), {}, ('y',), 'should be last', 99999), - (3, f, (3,), {}, ('y',)), - (None, f, (5,), {}, ('y',)), - ]) + + result = self._callFUT( + [ + (None, f), + (1, f, (1,), {}, (), 'first'), + (1, f, (2,), {}, ('x',), 'second'), + (1, f, (3,), {}, ('y',), 'third'), + (4, f, (4,), {}, ('y',), 'should be last', 99999), + (3, f, (3,), {}, ('y',)), + (None, f, (5,), {}, ('y',)), + ] + ) result = list(result) self.assertEqual( result, - [{'info': None, - 'args': (), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': None, - 'includepath': (), - 'order': 0}, - - {'info': 'first', - 'args': (1,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 1, - 'includepath': (), - 'order': 0}, - - {'info': None, - 'args': (3,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 3, - 'includepath': ('y',), - 'order': 0}, - - {'info': None, - 'args': (5,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': None, - 'includepath': ('y',), - 'order': 0}, - - {'info': 'should be last', - 'args': (4,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 4, - 'includepath': ('y',), - 'order': 99999} - ] - ) + [ + { + 'info': None, + 'args': (), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': None, + 'includepath': (), + 'order': 0, + }, + { + 'info': 'first', + 'args': (1,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 1, + 'includepath': (), + 'order': 0, + }, + { + 'info': None, + 'args': (3,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 3, + 'includepath': ('y',), + 'order': 0, + }, + { + 'info': None, + 'args': (5,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': None, + 'includepath': ('y',), + 'order': 0, + }, + { + 'info': 'should be last', + 'args': (4,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 4, + 'includepath': ('y',), + 'order': 99999, + }, + ], + ) def test_it_success_dicts(self): from . import dummyfactory as f - result = self._callFUT([ - (None, f), - (1, f, (1,), {}, (), 'first'), - (1, f, (2,), {}, ('x',), 'second'), - (1, f, (3,), {}, ('y',), 'third'), - (4, f, (4,), {}, ('y',), 'should be last', 99999), - (3, f, (3,), {}, ('y',)), - (None, f, (5,), {}, ('y',)), - ]) + + result = self._callFUT( + [ + (None, f), + (1, f, (1,), {}, (), 'first'), + (1, f, (2,), {}, ('x',), 'second'), + (1, f, (3,), {}, ('y',), 'third'), + (4, f, (4,), {}, ('y',), 'should be last', 99999), + (3, f, (3,), {}, ('y',)), + (None, f, (5,), {}, ('y',)), + ] + ) result = list(result) self.assertEqual( result, - [{'info': None, - 'args': (), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': None, - 'includepath': (), - 'order': 0}, - - {'info': 'first', - 'args': (1,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 1, - 'includepath': (), - 'order': 0}, - - {'info': None, - 'args': (3,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 3, - 'includepath': ('y',), - 'order': 0}, - - {'info': None, - 'args': (5,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': None, - 'includepath': ('y',), - 'order': 0}, - - {'info': 'should be last', - 'args': (4,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 4, - 'includepath': ('y',), - 'order': 99999} - ] - ) + [ + { + 'info': None, + 'args': (), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': None, + 'includepath': (), + 'order': 0, + }, + { + 'info': 'first', + 'args': (1,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 1, + 'includepath': (), + 'order': 0, + }, + { + 'info': None, + 'args': (3,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 3, + 'includepath': ('y',), + 'order': 0, + }, + { + 'info': None, + 'args': (5,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': None, + 'includepath': ('y',), + 'order': 0, + }, + { + 'info': 'should be last', + 'args': (4,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 4, + 'includepath': ('y',), + 'order': 99999, + }, + ], + ) def test_it_conflict(self): from . import dummyfactory as f - result = self._callFUT([ - (None, f), - (1, f, (2,), {}, ('x',), 'eek'), # will conflict - (1, f, (3,), {}, ('y',), 'ack'), # will conflict - (4, f, (4,), {}, ('y',)), - (3, f, (3,), {}, ('y',)), - (None, f, (5,), {}, ('y',)), - ]) + + result = self._callFUT( + [ + (None, f), + (1, f, (2,), {}, ('x',), 'eek'), # will conflict + (1, f, (3,), {}, ('y',), 'ack'), # will conflict + (4, f, (4,), {}, ('y',)), + (3, f, (3,), {}, ('y',)), + (None, f, (5,), {}, ('y',)), + ] + ) self.assertRaises(ConfigurationConflictError, list, result) def test_it_with_actions_grouped_by_order(self): from . import dummyfactory as f - result = self._callFUT([ - (None, f), # X - (1, f, (1,), {}, (), 'third', 10), # X - (1, f, (2,), {}, ('x',), 'fourth', 10), - (1, f, (3,), {}, ('y',), 'fifth', 10), - (2, f, (1,), {}, (), 'sixth', 10), # X - (3, f, (1,), {}, (), 'seventh', 10), # X - (5, f, (4,), {}, ('y',), 'eighth', 99999), # X - (4, f, (3,), {}, (), 'first', 5), # X - (4, f, (5,), {}, ('y',), 'second', 5), - ]) + + result = self._callFUT( + [ + (None, f), # X + (1, f, (1,), {}, (), 'third', 10), # X + (1, f, (2,), {}, ('x',), 'fourth', 10), + (1, f, (3,), {}, ('y',), 'fifth', 10), + (2, f, (1,), {}, (), 'sixth', 10), # X + (3, f, (1,), {}, (), 'seventh', 10), # X + (5, f, (4,), {}, ('y',), 'eighth', 99999), # X + (4, f, (3,), {}, (), 'first', 5), # X + (4, f, (5,), {}, ('y',), 'second', 5), + ] + ) result = list(result) self.assertEqual(len(result), 6) # resolved actions should be grouped by (order, i) self.assertEqual( result, - [{'info': None, - 'args': (), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': None, - 'includepath': (), - 'order': 0}, - - {'info': 'first', - 'args': (3,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 4, - 'includepath': (), - 'order': 5}, - - {'info': 'third', - 'args': (1,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 1, - 'includepath': (), - 'order': 10}, - - {'info': 'sixth', - 'args': (1,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 2, - 'includepath': (), - 'order': 10}, - - {'info': 'seventh', - 'args': (1,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 3, - 'includepath': (), - 'order': 10}, - - {'info': 'eighth', - 'args': (4,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 5, - 'includepath': ('y',), - 'order': 99999} - ] - ) + [ + { + 'info': None, + 'args': (), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': None, + 'includepath': (), + 'order': 0, + }, + { + 'info': 'first', + 'args': (3,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 4, + 'includepath': (), + 'order': 5, + }, + { + 'info': 'third', + 'args': (1,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 1, + 'includepath': (), + 'order': 10, + }, + { + 'info': 'sixth', + 'args': (1,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 2, + 'includepath': (), + 'order': 10, + }, + { + 'info': 'seventh', + 'args': (1,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 3, + 'includepath': (), + 'order': 10, + }, + { + 'info': 'eighth', + 'args': (4,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 5, + 'includepath': ('y',), + 'order': 99999, + }, + ], + ) def test_override_success_across_orders(self): from . import dummyfactory as f - result = self._callFUT([ - (1, f, (2,), {}, ('x',), 'eek', 0), - (1, f, (3,), {}, ('x', 'y'), 'ack', 10), - ]) + + result = self._callFUT( + [ + (1, f, (2,), {}, ('x',), 'eek', 0), + (1, f, (3,), {}, ('x', 'y'), 'ack', 10), + ] + ) result = list(result) - self.assertEqual(result, [ - {'info': 'eek', - 'args': (2,), - 'callable': f, - 'introspectables': (), - 'kw': {}, - 'discriminator': 1, - 'includepath': ('x',), - 'order': 0}, - ]) + self.assertEqual( + result, + [ + { + 'info': 'eek', + 'args': (2,), + 'callable': f, + 'introspectables': (), + 'kw': {}, + 'discriminator': 1, + 'includepath': ('x',), + 'order': 0, + } + ], + ) def test_conflicts_across_orders(self): from . import dummyfactory as f - result = self._callFUT([ - (1, f, (2,), {}, ('x', 'y'), 'eek', 0), - (1, f, (3,), {}, ('x'), 'ack', 10), - ]) + + result = self._callFUT( + [ + (1, f, (2,), {}, ('x', 'y'), 'eek', 0), + (1, f, (3,), {}, ('x'), 'ack', 10), + ] + ) self.assertRaises(ConfigurationConflictError, list, result) + class TestGlobalRegistriesIntegration(unittest.TestCase): def setUp(self): from pyramid.config import global_registries + global_registries.empty() tearDown = setUp def _makeConfigurator(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_global_registries_empty(self): from pyramid.config import global_registries + self.assertEqual(global_registries.last, None) def test_global_registries(self): from pyramid.config import global_registries + config1 = self._makeConfigurator() config1.make_wsgi_app() self.assertEqual(global_registries.last, config1.registry) config2 = self._makeConfigurator() config2.make_wsgi_app() self.assertEqual(global_registries.last, config2.registry) - self.assertEqual(list(global_registries), - [config1.registry, config2.registry]) + self.assertEqual( + list(global_registries), [config1.registry, config2.registry] + ) global_registries.remove(config2.registry) self.assertEqual(global_registries.last, config1.registry) + class DummyRequest: subpath = () matchdict = None request_iface = IRequest + def __init__(self, environ=None): if environ is None: environ = {} @@ -2005,63 +2413,86 @@ class DummyRequest: self.params = {} self.cookies = {} + class DummyThreadLocalManager(object): def __init__(self): self.pushed = {'registry': None, 'request': None} self.popped = False + def push(self, d): self.pushed = d + def get(self): return self.pushed + def pop(self): self.popped = True + from zope.interface import implementer + + @implementer(IDummy) class DummyEvent: pass + class DummyRegistry(object): def __init__(self, adaptation=None, util=None): self.utilities = [] self.adapters = [] self.adaptation = adaptation self.util = util + def subscribers(self, events, name): self.events = events return events + def registerUtility(self, *arg, **kw): self.utilities.append((arg, kw)) + def registerAdapter(self, *arg, **kw): self.adapters.append((arg, kw)) + def queryAdapter(self, *arg, **kw): return self.adaptation + def queryUtility(self, *arg, **kw): return self.util + from zope.interface import Interface + + class IOther(Interface): pass + def _conflictFunctions(e): conflicts = e._conflicts.values() for conflict in conflicts: for confinst in conflict: yield confinst.function + class DummyActionState(object): autocommit = False info = '' + def __init__(self): self.actions = [] + def action(self, *arg, **kw): self.actions.append((arg, kw)) + class DummyIntrospectable(object): def __init__(self): self.registered = [] + def register(self, introspector, action_info): self.registered.append((introspector, action_info)) - + + class DummyPredicate(object): pass diff --git a/tests/test_config/test_rendering.py b/tests/test_config/test_rendering.py index 8794fa9df..a33977c28 100644 --- a/tests/test_config/test_rendering.py +++ b/tests/test_config/test_rendering.py @@ -1,34 +1,43 @@ import unittest + class TestRenderingConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_add_default_renderers(self): from pyramid.config.rendering import DEFAULT_RENDERERS from pyramid.interfaces import IRendererFactory + config = self._makeOne(autocommit=True) config.add_default_renderers() for name, impl in DEFAULT_RENDERERS: self.assertTrue( - config.registry.queryUtility(IRendererFactory, name) is not None - ) + config.registry.queryUtility(IRendererFactory, name) + is not None + ) def test_add_renderer(self): from pyramid.interfaces import IRendererFactory + config = self._makeOne(autocommit=True) renderer = object() config.add_renderer('name', renderer) - self.assertEqual(config.registry.getUtility(IRendererFactory, 'name'), - renderer) + self.assertEqual( + config.registry.getUtility(IRendererFactory, 'name'), renderer + ) def test_add_renderer_dottedname_factory(self): from pyramid.interfaces import IRendererFactory + config = self._makeOne(autocommit=True) import tests.test_config - config.add_renderer('name', 'tests.test_config') - self.assertEqual(config.registry.getUtility(IRendererFactory, 'name'), - tests.test_config) + config.add_renderer('name', 'tests.test_config') + self.assertEqual( + config.registry.getUtility(IRendererFactory, 'name'), + tests.test_config, + ) diff --git a/tests/test_config/test_routes.py b/tests/test_config/test_routes.py index 870abe0ee..0999f8072 100644 --- a/tests/test_config/test_routes.py +++ b/tests/test_config/test_routes.py @@ -4,14 +4,17 @@ from . import dummyfactory from . import DummyContext from pyramid.compat import text_ + class RoutesConfiguratorMixinTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def _assertRoute(self, config, name, path, num_predicates=0): from pyramid.interfaces import IRoutesMapper + mapper = config.registry.getUtility(IRoutesMapper) routes = mapper.get_routes() route = routes[0] @@ -33,6 +36,7 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_get_routes_mapper_already_registered(self): from pyramid.interfaces import IRoutesMapper + config = self._makeOne() mapper = object() config.registry.registerUtility(mapper, IRoutesMapper) @@ -53,8 +57,9 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_discriminator(self): config = self._makeOne() config.add_route('name', 'path') - self.assertEqual(config.action_state.actions[-1]['discriminator'], - ('route', 'name')) + self.assertEqual( + config.action_state.actions[-1]['discriminator'], ('route', 'name') + ) def test_add_route_with_factory(self): config = self._makeOne(autocommit=True) @@ -68,13 +73,13 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): config.add_route('name', 'path/{foo}', static=True) mapper = config.get_routes_mapper() self.assertEqual(len(mapper.get_routes()), 0) - self.assertEqual(mapper.generate('name', {"foo":"a"}), '/path/a') + self.assertEqual(mapper.generate('name', {"foo": "a"}), '/path/a') def test_add_route_with_factory_dottedname(self): config = self._makeOne(autocommit=True) config.add_route( - 'name', 'path', - factory='tests.test_config.dummyfactory') + 'name', 'path', factory='tests.test_config.dummyfactory' + ) route = self._assertRoute(config, 'name', 'path') self.assertEqual(route.factory, dummyfactory) @@ -116,8 +121,9 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_with_path_info_highorder(self): config = self._makeOne(autocommit=True) - config.add_route('name', 'path', - path_info=text_(b'/La Pe\xc3\xb1a', 'utf-8')) + config.add_route( + 'name', 'path', path_info=text_(b'/La Pe\xc3\xb1a', 'utf-8') + ) route = self._assertRoute(config, 'name', 'path', 1) predicate = route.predicates[0] request = self._makeRequest(config) @@ -129,8 +135,9 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_with_path_info_regex(self): config = self._makeOne(autocommit=True) - config.add_route('name', 'path', - path_info=text_(br'/La Pe\w*', 'utf-8')) + config.add_route( + 'name', 'path', path_info=text_(br'/La Pe\w*', 'utf-8') + ) route = self._assertRoute(config, 'name', 'path', 1) predicate = route.predicates[0] request = self._makeRequest(config) @@ -146,7 +153,7 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): route = self._assertRoute(config, 'name', 'path', 1) predicate = route.predicates[0] request = self._makeRequest(config) - request.params = {'abc':'123'} + request.params = {'abc': '123'} self.assertEqual(predicate(None, request), True) request = self._makeRequest(config) request.params = {} @@ -154,9 +161,15 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_with_custom_predicates(self): import warnings + config = self._makeOne(autocommit=True) - def pred1(context, request): pass - def pred2(context, request): pass + + def pred1(context, request): + pass + + def pred2(context, request): + pass + with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always') config.add_route('name', 'path', custom_predicates=(pred1, pred2)) @@ -170,7 +183,7 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): route = self._assertRoute(config, 'name', 'path', 1) predicate = route.predicates[0] request = self._makeRequest(config) - request.headers = {'Host':'example.com'} + request.headers = {'Host': 'example.com'} self.assertEqual(predicate(None, request), True) request = self._makeRequest(config) request.headers = {} @@ -222,6 +235,7 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_no_path_no_pattern(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() self.assertRaises(ConfigurationError, config.add_route, 'name') @@ -234,46 +248,52 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_no_view_with_view_attr(self): config = self._makeOne(autocommit=True) from pyramid.exceptions import ConfigurationError + try: config.add_route('name', '/pattern', view_attr='abc') except ConfigurationError: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_add_route_no_view_with_view_context(self): config = self._makeOne(autocommit=True) from pyramid.exceptions import ConfigurationError + try: config.add_route('name', '/pattern', view_context=DummyContext) except ConfigurationError: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_add_route_no_view_with_view_permission(self): config = self._makeOne(autocommit=True) from pyramid.exceptions import ConfigurationError + try: config.add_route('name', '/pattern', view_permission='edit') except ConfigurationError: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_add_route_no_view_with_view_renderer(self): config = self._makeOne(autocommit=True) from pyramid.exceptions import ConfigurationError + try: config.add_route('name', '/pattern', view_renderer='json') except ConfigurationError: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError + class DummyRequest: subpath = () matchdict = None + def __init__(self, environ=None): if environ is None: environ = {} @@ -281,6 +301,7 @@ class DummyRequest: self.params = {} self.cookies = {} + class DummyAccept(object): def __init__(self, *matches, **kw): self.matches = list(matches) diff --git a/tests/test_config/test_security.py b/tests/test_config/test_security.py index 5db8e21fc..77f7f0440 100644 --- a/tests/test_config/test_security.py +++ b/tests/test_config/test_security.py @@ -3,9 +3,11 @@ import unittest from pyramid.exceptions import ConfigurationExecutionError from pyramid.exceptions import ConfigurationError + class ConfiguratorSecurityMethodsTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config @@ -18,12 +20,14 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): def test_set_authentication_policy_no_authz_policy_autocommit(self): config = self._makeOne(autocommit=True) policy = object() - self.assertRaises(ConfigurationError, - config.set_authentication_policy, policy) + self.assertRaises( + ConfigurationError, config.set_authentication_policy, policy + ) def test_set_authentication_policy_with_authz_policy(self): from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy + config = self._makeOne() authn_policy = object() authz_policy = object() @@ -31,11 +35,13 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): config.set_authentication_policy(authn_policy) config.commit() self.assertEqual( - config.registry.getUtility(IAuthenticationPolicy), authn_policy) + config.registry.getUtility(IAuthenticationPolicy), authn_policy + ) def test_set_authentication_policy_with_authz_policy_autocommit(self): from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy + config = self._makeOne(autocommit=True) authn_policy = object() authz_policy = object() @@ -43,7 +49,8 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): config.set_authentication_policy(authn_policy) config.commit() self.assertEqual( - config.registry.getUtility(IAuthenticationPolicy), authn_policy) + config.registry.getUtility(IAuthenticationPolicy), authn_policy + ) def test_set_authorization_policy_no_authn_policy(self): config = self._makeOne() @@ -53,15 +60,18 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): def test_set_authorization_policy_no_authn_policy_autocommit(self): from pyramid.interfaces import IAuthorizationPolicy + config = self._makeOne(autocommit=True) policy = object() config.set_authorization_policy(policy) self.assertEqual( - config.registry.getUtility(IAuthorizationPolicy), policy) + config.registry.getUtility(IAuthorizationPolicy), policy + ) def test_set_authorization_policy_with_authn_policy(self): from pyramid.interfaces import IAuthorizationPolicy from pyramid.interfaces import IAuthenticationPolicy + config = self._makeOne() authn_policy = object() authz_policy = object() @@ -69,25 +79,30 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): config.set_authorization_policy(authz_policy) config.commit() self.assertEqual( - config.registry.getUtility(IAuthorizationPolicy), authz_policy) + config.registry.getUtility(IAuthorizationPolicy), authz_policy + ) def test_set_authorization_policy_with_authn_policy_autocommit(self): from pyramid.interfaces import IAuthorizationPolicy from pyramid.interfaces import IAuthenticationPolicy + config = self._makeOne(autocommit=True) authn_policy = object() authz_policy = object() config.registry.registerUtility(authn_policy, IAuthenticationPolicy) config.set_authorization_policy(authz_policy) self.assertEqual( - config.registry.getUtility(IAuthorizationPolicy), authz_policy) + config.registry.getUtility(IAuthorizationPolicy), authz_policy + ) def test_set_default_permission(self): from pyramid.interfaces import IDefaultPermission + config = self._makeOne(autocommit=True) config.set_default_permission('view') - self.assertEqual(config.registry.getUtility(IDefaultPermission), - 'view') + self.assertEqual( + config.registry.getUtility(IDefaultPermission), 'view' + ) def test_add_permission(self): config = self._makeOne(autocommit=True) @@ -100,23 +115,34 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase): def test_set_default_csrf_options(self): from pyramid.interfaces import IDefaultCSRFOptions + config = self._makeOne(autocommit=True) config.set_default_csrf_options() result = config.registry.getUtility(IDefaultCSRFOptions) self.assertEqual(result.require_csrf, True) self.assertEqual(result.token, 'csrf_token') self.assertEqual(result.header, 'X-CSRF-Token') - self.assertEqual(list(sorted(result.safe_methods)), - ['GET', 'HEAD', 'OPTIONS', 'TRACE']) + self.assertEqual( + list(sorted(result.safe_methods)), + ['GET', 'HEAD', 'OPTIONS', 'TRACE'], + ) self.assertTrue(result.callback is None) def test_changing_set_default_csrf_options(self): from pyramid.interfaces import IDefaultCSRFOptions + config = self._makeOne(autocommit=True) - def callback(request): return True + + def callback(request): + return True + config.set_default_csrf_options( - require_csrf=False, token='DUMMY', header=None, - safe_methods=('PUT',), callback=callback) + require_csrf=False, + token='DUMMY', + header=None, + safe_methods=('PUT',), + callback=callback, + ) result = config.registry.getUtility(IDefaultCSRFOptions) self.assertEqual(result.require_csrf, False) self.assertEqual(result.token, 'DUMMY') diff --git a/tests/test_config/test_settings.py b/tests/test_config/test_settings.py index a3afd24e7..2fe769add 100644 --- a/tests/test_config/test_settings.py +++ b/tests/test_config/test_settings.py @@ -4,6 +4,7 @@ import unittest class TestSettingsConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config @@ -21,27 +22,29 @@ class TestSettingsConfiguratorMixin(unittest.TestCase): def test__set_settings_as_dictwithvalues(self): config = self._makeOne() - settings = config._set_settings({'a':'1'}) + settings = config._set_settings({'a': '1'}) self.assertEqual(settings['a'], '1') def test_get_settings_nosettings(self): from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg) self.assertEqual(config.get_settings(), None) def test_get_settings_withsettings(self): - settings = {'a':1} + settings = {'a': 1} config = self._makeOne() config.registry.settings = settings self.assertEqual(config.get_settings(), settings) def test_add_settings_settings_already_registered(self): from pyramid.registry import Registry + reg = Registry() config = self._makeOne(reg) - config._set_settings({'a':1}) - config.add_settings({'b':2}) + config._set_settings({'a': 1}) + config.add_settings({'b': 2}) settings = reg.settings self.assertEqual(settings['a'], 1) self.assertEqual(settings['b'], 2) @@ -49,15 +52,17 @@ class TestSettingsConfiguratorMixin(unittest.TestCase): def test_add_settings_settings_not_yet_registered(self): from pyramid.registry import Registry from pyramid.interfaces import ISettings + reg = Registry() config = self._makeOne(reg) - config.add_settings({'a':1}) + config.add_settings({'a': 1}) settings = reg.getUtility(ISettings) self.assertEqual(settings['a'], 1) def test_add_settings_settings_None(self): from pyramid.registry import Registry from pyramid.interfaces import ISettings + reg = Registry() config = self._makeOne(reg) config.add_settings(None, a=1) @@ -68,6 +73,7 @@ class TestSettingsConfiguratorMixin(unittest.TestCase): class ReadOnlyDict(dict): def __readonly__(self, *args, **kwargs): # pragma: no cover raise RuntimeError("Cannot modify ReadOnlyDict") + __setitem__ = __readonly__ __delitem__ = __readonly__ pop = __readonly__ @@ -83,9 +89,9 @@ class TestSettingsConfiguratorMixin(unittest.TestCase): class TestSettings(unittest.TestCase): - def _getTargetClass(self): from pyramid.config.settings import Settings + return Settings def _makeOne(self, d=None, environ=None): @@ -112,28 +118,30 @@ class TestSettings(unittest.TestCase): settings = self._makeOne({}) self.assertEqual(settings['prevent_http_cache'], False) self.assertEqual(settings['pyramid.prevent_http_cache'], False) - result = self._makeOne({'prevent_http_cache':'false'}) + result = self._makeOne({'prevent_http_cache': 'false'}) self.assertEqual(result['prevent_http_cache'], False) self.assertEqual(result['pyramid.prevent_http_cache'], False) - result = self._makeOne({'prevent_http_cache':'t'}) + result = self._makeOne({'prevent_http_cache': 't'}) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) - result = self._makeOne({'prevent_http_cache':'1'}) + result = self._makeOne({'prevent_http_cache': '1'}) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) - result = self._makeOne({'pyramid.prevent_http_cache':'t'}) + result = self._makeOne({'pyramid.prevent_http_cache': 't'}) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) - result = self._makeOne({}, {'PYRAMID_PREVENT_HTTP_CACHE':'1'}) + result = self._makeOne({}, {'PYRAMID_PREVENT_HTTP_CACHE': '1'}) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) - result = self._makeOne({'prevent_http_cache':'false', - 'pyramid.prevent_http_cache':'1'}) + result = self._makeOne( + {'prevent_http_cache': 'false', 'pyramid.prevent_http_cache': '1'} + ) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) - result = self._makeOne({'prevent_http_cache':'false', - 'pyramid.prevent_http_cache':'f'}, - {'PYRAMID_PREVENT_HTTP_CACHE':'1'}) + result = self._makeOne( + {'prevent_http_cache': 'false', 'pyramid.prevent_http_cache': 'f'}, + {'PYRAMID_PREVENT_HTTP_CACHE': '1'}, + ) self.assertEqual(result['prevent_http_cache'], True) self.assertEqual(result['pyramid.prevent_http_cache'], True) @@ -141,28 +149,30 @@ class TestSettings(unittest.TestCase): settings = self._makeOne({}) self.assertEqual(settings['prevent_cachebust'], False) self.assertEqual(settings['pyramid.prevent_cachebust'], False) - result = self._makeOne({'prevent_cachebust':'false'}) + result = self._makeOne({'prevent_cachebust': 'false'}) self.assertEqual(result['prevent_cachebust'], False) self.assertEqual(result['pyramid.prevent_cachebust'], False) - result = self._makeOne({'prevent_cachebust':'t'}) + result = self._makeOne({'prevent_cachebust': 't'}) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) - result = self._makeOne({'prevent_cachebust':'1'}) + result = self._makeOne({'prevent_cachebust': '1'}) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) - result = self._makeOne({'pyramid.prevent_cachebust':'t'}) + result = self._makeOne({'pyramid.prevent_cachebust': 't'}) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) - result = self._makeOne({}, {'PYRAMID_PREVENT_CACHEBUST':'1'}) + result = self._makeOne({}, {'PYRAMID_PREVENT_CACHEBUST': '1'}) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) - result = self._makeOne({'prevent_cachebust':'false', - 'pyramid.prevent_cachebust':'1'}) + result = self._makeOne( + {'prevent_cachebust': 'false', 'pyramid.prevent_cachebust': '1'} + ) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) - result = self._makeOne({'prevent_cachebust':'false', - 'pyramid.prevent_cachebust':'f'}, - {'PYRAMID_PREVENT_CACHEBUST':'1'}) + result = self._makeOne( + {'prevent_cachebust': 'false', 'pyramid.prevent_cachebust': 'f'}, + {'PYRAMID_PREVENT_CACHEBUST': '1'}, + ) self.assertEqual(result['prevent_cachebust'], True) self.assertEqual(result['pyramid.prevent_cachebust'], True) @@ -170,27 +180,29 @@ class TestSettings(unittest.TestCase): settings = self._makeOne({}) self.assertEqual(settings['reload_templates'], False) self.assertEqual(settings['pyramid.reload_templates'], False) - result = self._makeOne({'reload_templates':'false'}) + result = self._makeOne({'reload_templates': 'false'}) self.assertEqual(result['reload_templates'], False) self.assertEqual(result['pyramid.reload_templates'], False) - result = self._makeOne({'reload_templates':'t'}) + result = self._makeOne({'reload_templates': 't'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) - result = self._makeOne({'reload_templates':'1'}) + result = self._makeOne({'reload_templates': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) - result = self._makeOne({'pyramid.reload_templates':'1'}) + result = self._makeOne({'pyramid.reload_templates': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) - result = self._makeOne({}, {'PYRAMID_RELOAD_TEMPLATES':'1'}) + result = self._makeOne({}, {'PYRAMID_RELOAD_TEMPLATES': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) - result = self._makeOne({'reload_templates':'false', - 'pyramid.reload_templates':'1'}) + result = self._makeOne( + {'reload_templates': 'false', 'pyramid.reload_templates': '1'} + ) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) - result = self._makeOne({'reload_templates':'false'}, - {'PYRAMID_RELOAD_TEMPLATES':'1'}) + result = self._makeOne( + {'reload_templates': 'false'}, {'PYRAMID_RELOAD_TEMPLATES': '1'} + ) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['pyramid.reload_templates'], True) @@ -201,40 +213,42 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['reload_assets'], False) self.assertEqual(result['pyramid.reload_resources'], False) self.assertEqual(result['pyramid.reload_assets'], False) - result = self._makeOne({'reload_resources':'false'}) + result = self._makeOne({'reload_resources': 'false'}) self.assertEqual(result['reload_resources'], False) self.assertEqual(result['reload_assets'], False) self.assertEqual(result['pyramid.reload_resources'], False) self.assertEqual(result['pyramid.reload_assets'], False) - result = self._makeOne({'reload_resources':'t'}) + result = self._makeOne({'reload_resources': 't'}) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_resources':'1'}) + result = self._makeOne({'reload_resources': '1'}) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'pyramid.reload_resources':'1'}) + result = self._makeOne({'pyramid.reload_resources': '1'}) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({}, {'PYRAMID_RELOAD_RESOURCES':'1'}) + result = self._makeOne({}, {'PYRAMID_RELOAD_RESOURCES': '1'}) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_resources':'false', - 'pyramid.reload_resources':'1'}) + result = self._makeOne( + {'reload_resources': 'false', 'pyramid.reload_resources': '1'} + ) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_resources':'false', - 'pyramid.reload_resources':'false'}, - {'PYRAMID_RELOAD_RESOURCES':'1'}) + result = self._makeOne( + {'reload_resources': 'false', 'pyramid.reload_resources': 'false'}, + {'PYRAMID_RELOAD_RESOURCES': '1'}, + ) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) @@ -247,40 +261,42 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['reload_resources'], False) self.assertEqual(result['pyramid.reload_assets'], False) self.assertEqual(result['pyramid.reload_resources'], False) - result = self._makeOne({'reload_assets':'false'}) + result = self._makeOne({'reload_assets': 'false'}) self.assertEqual(result['reload_resources'], False) self.assertEqual(result['reload_assets'], False) self.assertEqual(result['pyramid.reload_assets'], False) self.assertEqual(result['pyramid.reload_resources'], False) - result = self._makeOne({'reload_assets':'t'}) + result = self._makeOne({'reload_assets': 't'}) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) - result = self._makeOne({'reload_assets':'1'}) + result = self._makeOne({'reload_assets': '1'}) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) - result = self._makeOne({'pyramid.reload_assets':'1'}) + result = self._makeOne({'pyramid.reload_assets': '1'}) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) - result = self._makeOne({}, {'PYRAMID_RELOAD_ASSETS':'1'}) + result = self._makeOne({}, {'PYRAMID_RELOAD_ASSETS': '1'}) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) - result = self._makeOne({'reload_assets':'false', - 'pyramid.reload_assets':'1'}) + result = self._makeOne( + {'reload_assets': 'false', 'pyramid.reload_assets': '1'} + ) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) self.assertEqual(result['pyramid.reload_resources'], True) - result = self._makeOne({'reload_assets':'false', - 'pyramid.reload_assets':'false'}, - {'PYRAMID_RELOAD_ASSETS':'1'}) + result = self._makeOne( + {'reload_assets': 'false', 'pyramid.reload_assets': 'false'}, + {'PYRAMID_RELOAD_ASSETS': '1'}, + ) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) @@ -294,52 +310,54 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.reload_templates'], False) self.assertEqual(result['pyramid.reload_resources'], False) self.assertEqual(result['pyramid.reload_assets'], False) - result = self._makeOne({'reload_all':'false'}) + result = self._makeOne({'reload_all': 'false'}) self.assertEqual(result['reload_templates'], False) self.assertEqual(result['reload_resources'], False) self.assertEqual(result['reload_assets'], False) self.assertEqual(result['pyramid.reload_templates'], False) self.assertEqual(result['pyramid.reload_resources'], False) self.assertEqual(result['pyramid.reload_assets'], False) - result = self._makeOne({'reload_all':'t'}) + result = self._makeOne({'reload_all': 't'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_templates'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_all':'1'}) + result = self._makeOne({'reload_all': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_templates'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'pyramid.reload_all':'1'}) + result = self._makeOne({'pyramid.reload_all': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_templates'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({}, {'PYRAMID_RELOAD_ALL':'1'}) + result = self._makeOne({}, {'PYRAMID_RELOAD_ALL': '1'}) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_templates'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_all':'false', - 'pyramid.reload_all':'1'}) + result = self._makeOne( + {'reload_all': 'false', 'pyramid.reload_all': '1'} + ) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) self.assertEqual(result['pyramid.reload_templates'], True) self.assertEqual(result['pyramid.reload_resources'], True) self.assertEqual(result['pyramid.reload_assets'], True) - result = self._makeOne({'reload_all':'false', - 'pyramid.reload_all':'false'}, - {'PYRAMID_RELOAD_ALL':'1'}) + result = self._makeOne( + {'reload_all': 'false', 'pyramid.reload_all': 'false'}, + {'PYRAMID_RELOAD_ALL': '1'}, + ) self.assertEqual(result['reload_templates'], True) self.assertEqual(result['reload_resources'], True) self.assertEqual(result['reload_assets'], True) @@ -351,28 +369,36 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['debug_authorization'], False) self.assertEqual(result['pyramid.debug_authorization'], False) - result = self._makeOne({'debug_authorization':'false'}) + result = self._makeOne({'debug_authorization': 'false'}) self.assertEqual(result['debug_authorization'], False) self.assertEqual(result['pyramid.debug_authorization'], False) - result = self._makeOne({'debug_authorization':'t'}) + result = self._makeOne({'debug_authorization': 't'}) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) - result = self._makeOne({'debug_authorization':'1'}) + result = self._makeOne({'debug_authorization': '1'}) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) - result = self._makeOne({'pyramid.debug_authorization':'1'}) + result = self._makeOne({'pyramid.debug_authorization': '1'}) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) - result = self._makeOne({}, {'PYRAMID_DEBUG_AUTHORIZATION':'1'}) + result = self._makeOne({}, {'PYRAMID_DEBUG_AUTHORIZATION': '1'}) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) - result = self._makeOne({'debug_authorization':'false', - 'pyramid.debug_authorization':'1'}) + result = self._makeOne( + { + 'debug_authorization': 'false', + 'pyramid.debug_authorization': '1', + } + ) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) - result = self._makeOne({'debug_authorization':'false', - 'pyramid.debug_authorization':'false'}, - {'PYRAMID_DEBUG_AUTHORIZATION':'1'}) + result = self._makeOne( + { + 'debug_authorization': 'false', + 'pyramid.debug_authorization': 'false', + }, + {'PYRAMID_DEBUG_AUTHORIZATION': '1'}, + ) self.assertEqual(result['debug_authorization'], True) self.assertEqual(result['pyramid.debug_authorization'], True) @@ -380,28 +406,30 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['debug_notfound'], False) self.assertEqual(result['pyramid.debug_notfound'], False) - result = self._makeOne({'debug_notfound':'false'}) + result = self._makeOne({'debug_notfound': 'false'}) self.assertEqual(result['debug_notfound'], False) self.assertEqual(result['pyramid.debug_notfound'], False) - result = self._makeOne({'debug_notfound':'t'}) + result = self._makeOne({'debug_notfound': 't'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) - result = self._makeOne({'debug_notfound':'1'}) + result = self._makeOne({'debug_notfound': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) - result = self._makeOne({'pyramid.debug_notfound':'1'}) + result = self._makeOne({'pyramid.debug_notfound': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) - result = self._makeOne({}, {'PYRAMID_DEBUG_NOTFOUND':'1'}) + result = self._makeOne({}, {'PYRAMID_DEBUG_NOTFOUND': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) - result = self._makeOne({'debug_notfound':'false', - 'pyramid.debug_notfound':'1'}) + result = self._makeOne( + {'debug_notfound': 'false', 'pyramid.debug_notfound': '1'} + ) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) - result = self._makeOne({'debug_notfound':'false', - 'pyramid.debug_notfound':'false'}, - {'PYRAMID_DEBUG_NOTFOUND':'1'}) + result = self._makeOne( + {'debug_notfound': 'false', 'pyramid.debug_notfound': 'false'}, + {'PYRAMID_DEBUG_NOTFOUND': '1'}, + ) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['pyramid.debug_notfound'], True) @@ -409,28 +437,30 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['debug_routematch'], False) self.assertEqual(result['pyramid.debug_routematch'], False) - result = self._makeOne({'debug_routematch':'false'}) + result = self._makeOne({'debug_routematch': 'false'}) self.assertEqual(result['debug_routematch'], False) self.assertEqual(result['pyramid.debug_routematch'], False) - result = self._makeOne({'debug_routematch':'t'}) + result = self._makeOne({'debug_routematch': 't'}) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) - result = self._makeOne({'debug_routematch':'1'}) + result = self._makeOne({'debug_routematch': '1'}) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) - result = self._makeOne({'pyramid.debug_routematch':'1'}) + result = self._makeOne({'pyramid.debug_routematch': '1'}) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) - result = self._makeOne({}, {'PYRAMID_DEBUG_ROUTEMATCH':'1'}) + result = self._makeOne({}, {'PYRAMID_DEBUG_ROUTEMATCH': '1'}) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) - result = self._makeOne({'debug_routematch':'false', - 'pyramid.debug_routematch':'1'}) + result = self._makeOne( + {'debug_routematch': 'false', 'pyramid.debug_routematch': '1'} + ) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) - result = self._makeOne({'debug_routematch':'false', - 'pyramid.debug_routematch':'false'}, - {'PYRAMID_DEBUG_ROUTEMATCH':'1'}) + result = self._makeOne( + {'debug_routematch': 'false', 'pyramid.debug_routematch': 'false'}, + {'PYRAMID_DEBUG_ROUTEMATCH': '1'}, + ) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['pyramid.debug_routematch'], True) @@ -438,28 +468,30 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['debug_templates'], False) self.assertEqual(result['pyramid.debug_templates'], False) - result = self._makeOne({'debug_templates':'false'}) + result = self._makeOne({'debug_templates': 'false'}) self.assertEqual(result['debug_templates'], False) self.assertEqual(result['pyramid.debug_templates'], False) - result = self._makeOne({'debug_templates':'t'}) + result = self._makeOne({'debug_templates': 't'}) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_templates':'1'}) + result = self._makeOne({'debug_templates': '1'}) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'pyramid.debug_templates':'1'}) + result = self._makeOne({'pyramid.debug_templates': '1'}) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({}, {'PYRAMID_DEBUG_TEMPLATES':'1'}) + result = self._makeOne({}, {'PYRAMID_DEBUG_TEMPLATES': '1'}) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_templates':'false', - 'pyramid.debug_templates':'1'}) + result = self._makeOne( + {'debug_templates': 'false', 'pyramid.debug_templates': '1'} + ) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_templates':'false', - 'pyramid.debug_templates':'false'}, - {'PYRAMID_DEBUG_TEMPLATES':'1'}) + result = self._makeOne( + {'debug_templates': 'false', 'pyramid.debug_templates': 'false'}, + {'PYRAMID_DEBUG_TEMPLATES': '1'}, + ) self.assertEqual(result['debug_templates'], True) self.assertEqual(result['pyramid.debug_templates'], True) @@ -473,7 +505,7 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], False) self.assertEqual(result['pyramid.debug_authorization'], False) self.assertEqual(result['pyramid.debug_templates'], False) - result = self._makeOne({'debug_all':'false'}) + result = self._makeOne({'debug_all': 'false'}) self.assertEqual(result['debug_notfound'], False) self.assertEqual(result['debug_routematch'], False) self.assertEqual(result['debug_authorization'], False) @@ -482,7 +514,7 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], False) self.assertEqual(result['pyramid.debug_authorization'], False) self.assertEqual(result['pyramid.debug_templates'], False) - result = self._makeOne({'debug_all':'t'}) + result = self._makeOne({'debug_all': 't'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -491,7 +523,7 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], True) self.assertEqual(result['pyramid.debug_authorization'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_all':'1'}) + result = self._makeOne({'debug_all': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -500,7 +532,7 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], True) self.assertEqual(result['pyramid.debug_authorization'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'pyramid.debug_all':'1'}) + result = self._makeOne({'pyramid.debug_all': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -509,7 +541,7 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], True) self.assertEqual(result['pyramid.debug_authorization'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({}, {'PYRAMID_DEBUG_ALL':'1'}) + result = self._makeOne({}, {'PYRAMID_DEBUG_ALL': '1'}) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -518,8 +550,9 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], True) self.assertEqual(result['pyramid.debug_authorization'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_all':'false', - 'pyramid.debug_all':'1'}) + result = self._makeOne( + {'debug_all': 'false', 'pyramid.debug_all': '1'} + ) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -528,9 +561,10 @@ class TestSettings(unittest.TestCase): self.assertEqual(result['pyramid.debug_routematch'], True) self.assertEqual(result['pyramid.debug_authorization'], True) self.assertEqual(result['pyramid.debug_templates'], True) - result = self._makeOne({'debug_all':'false', - 'pyramid.debug_all':'false'}, - {'PYRAMID_DEBUG_ALL':'1'}) + result = self._makeOne( + {'debug_all': 'false', 'pyramid.debug_all': 'false'}, + {'PYRAMID_DEBUG_ALL': '1'}, + ) self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_routematch'], True) self.assertEqual(result['debug_authorization'], True) @@ -544,22 +578,30 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['default_locale_name'], 'en') self.assertEqual(result['pyramid.default_locale_name'], 'en') - result = self._makeOne({'default_locale_name':'abc'}) + result = self._makeOne({'default_locale_name': 'abc'}) self.assertEqual(result['default_locale_name'], 'abc') self.assertEqual(result['pyramid.default_locale_name'], 'abc') - result = self._makeOne({'pyramid.default_locale_name':'abc'}) + result = self._makeOne({'pyramid.default_locale_name': 'abc'}) self.assertEqual(result['default_locale_name'], 'abc') self.assertEqual(result['pyramid.default_locale_name'], 'abc') - result = self._makeOne({}, {'PYRAMID_DEFAULT_LOCALE_NAME':'abc'}) + result = self._makeOne({}, {'PYRAMID_DEFAULT_LOCALE_NAME': 'abc'}) self.assertEqual(result['default_locale_name'], 'abc') self.assertEqual(result['pyramid.default_locale_name'], 'abc') - result = self._makeOne({'default_locale_name':'def', - 'pyramid.default_locale_name':'abc'}) + result = self._makeOne( + { + 'default_locale_name': 'def', + 'pyramid.default_locale_name': 'abc', + } + ) self.assertEqual(result['default_locale_name'], 'abc') self.assertEqual(result['pyramid.default_locale_name'], 'abc') - result = self._makeOne({'default_locale_name':'def', - 'pyramid.default_locale_name':'ghi'}, - {'PYRAMID_DEFAULT_LOCALE_NAME':'abc'}) + result = self._makeOne( + { + 'default_locale_name': 'def', + 'pyramid.default_locale_name': 'ghi', + }, + {'PYRAMID_DEFAULT_LOCALE_NAME': 'abc'}, + ) self.assertEqual(result['default_locale_name'], 'abc') self.assertEqual(result['pyramid.default_locale_name'], 'abc') @@ -567,16 +609,27 @@ class TestSettings(unittest.TestCase): result = self._makeOne({}) self.assertEqual(result['pyramid.csrf_trusted_origins'], []) result = self._makeOne({'pyramid.csrf_trusted_origins': 'example.com'}) - self.assertEqual(result['pyramid.csrf_trusted_origins'], ['example.com']) - result = self._makeOne({'pyramid.csrf_trusted_origins': ['example.com']}) - self.assertEqual(result['pyramid.csrf_trusted_origins'], ['example.com']) - result = self._makeOne({'pyramid.csrf_trusted_origins': ( - 'example.com foo.example.com\nasdf.example.com')}) - self.assertEqual(result['pyramid.csrf_trusted_origins'], [ - 'example.com', 'foo.example.com', 'asdf.example.com']) + self.assertEqual( + result['pyramid.csrf_trusted_origins'], ['example.com'] + ) + result = self._makeOne( + {'pyramid.csrf_trusted_origins': ['example.com']} + ) + self.assertEqual( + result['pyramid.csrf_trusted_origins'], ['example.com'] + ) + result = self._makeOne( + { + 'pyramid.csrf_trusted_origins': ( + 'example.com foo.example.com\nasdf.example.com' + ) + } + ) + self.assertEqual( + result['pyramid.csrf_trusted_origins'], + ['example.com', 'foo.example.com', 'asdf.example.com'], + ) def test_originals_kept(self): - result = self._makeOne({'a':'i am so a'}) + result = self._makeOne({'a': 'i am so a'}) self.assertEqual(result['a'], 'i am so a') - - diff --git a/tests/test_config/test_testing.py b/tests/test_config/test_testing.py index 5be4e48d3..c0a98f9ad 100644 --- a/tests/test_config/test_testing.py +++ b/tests/test_config/test_testing.py @@ -4,19 +4,24 @@ from pyramid.compat import text_ from pyramid.security import AuthenticationAPIMixin, AuthorizationAPIMixin from . import IDummy + class TestingConfiguratorMixinTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_testing_securitypolicy(self): from pyramid.testing import DummySecurityPolicy + config = self._makeOne(autocommit=True) - config.testing_securitypolicy('user', ('group1', 'group2'), - permissive=False) + config.testing_securitypolicy( + 'user', ('group1', 'group2'), permissive=False + ) from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy + ut = config.registry.getUtility(IAuthenticationPolicy) self.assertTrue(isinstance(ut, DummySecurityPolicy)) ut = config.registry.getUtility(IAuthorizationPolicy) @@ -26,10 +31,14 @@ class TestingConfiguratorMixinTests(unittest.TestCase): def test_testing_securitypolicy_remember_result(self): from pyramid.security import remember + config = self._makeOne(autocommit=True) pol = config.testing_securitypolicy( - 'user', ('group1', 'group2'), - permissive=False, remember_result=True) + 'user', + ('group1', 'group2'), + permissive=False, + remember_result=True, + ) request = DummyRequest() request.registry = config.registry val = remember(request, 'fred') @@ -38,10 +47,11 @@ class TestingConfiguratorMixinTests(unittest.TestCase): def test_testing_securitypolicy_forget_result(self): from pyramid.security import forget + config = self._makeOne(autocommit=True) pol = config.testing_securitypolicy( - 'user', ('group1', 'group2'), - permissive=False, forget_result=True) + 'user', ('group1', 'group2'), permissive=False, forget_result=True + ) request = DummyRequest() request.registry = config.registry val = forget(request) @@ -51,27 +61,30 @@ class TestingConfiguratorMixinTests(unittest.TestCase): def test_testing_resources(self): from pyramid.traversal import find_resource from pyramid.interfaces import ITraverser + ob1 = object() ob2 = object() - resources = {'/ob1':ob1, '/ob2':ob2} + resources = {'/ob1': ob1, '/ob2': ob2} config = self._makeOne(autocommit=True) config.testing_resources(resources) adapter = config.registry.getAdapter(None, ITraverser) - result = adapter(DummyRequest({'PATH_INFO':'/ob1'})) + result = adapter(DummyRequest({'PATH_INFO': '/ob1'})) self.assertEqual(result['context'], ob1) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) self.assertEqual(result['traversed'], (text_('ob1'),)) self.assertEqual(result['virtual_root'], ob1) self.assertEqual(result['virtual_root_path'], ()) - result = adapter(DummyRequest({'PATH_INFO':'/ob2'})) + result = adapter(DummyRequest({'PATH_INFO': '/ob2'})) self.assertEqual(result['context'], ob2) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) self.assertEqual(result['traversed'], (text_('ob2'),)) self.assertEqual(result['virtual_root'], ob2) self.assertEqual(result['virtual_root_path'], ()) - self.assertRaises(KeyError, adapter, DummyRequest({'PATH_INFO':'/ob3'})) + self.assertRaises( + KeyError, adapter, DummyRequest({'PATH_INFO': '/ob3'}) + ) try: config.begin() self.assertEqual(find_resource(None, '/ob1'), ob1) @@ -90,8 +103,7 @@ class TestingConfiguratorMixinTests(unittest.TestCase): def test_testing_add_subscriber_dottedname(self): config = self._makeOne(autocommit=True) - L = config.testing_add_subscriber( - 'tests.test_config.test_init.IDummy') + L = config.testing_add_subscriber('tests.test_config.test_init.IDummy') event = DummyEvent() config.registry.notify(event) self.assertEqual(len(L), 1) @@ -101,6 +113,7 @@ class TestingConfiguratorMixinTests(unittest.TestCase): def test_testing_add_subscriber_multiple(self): from zope.interface import Interface + config = self._makeOne(autocommit=True) L = config.testing_add_subscriber((Interface, IDummy)) event = DummyEvent() @@ -125,13 +138,16 @@ class TestingConfiguratorMixinTests(unittest.TestCase): config = self._makeOne(autocommit=True) renderer = config.testing_add_renderer('templates/foo.pt') from pyramid.testing import DummyTemplateRenderer + self.assertTrue(isinstance(renderer, DummyTemplateRenderer)) from pyramid.renderers import render_to_response + # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry render_to_response( - 'templates/foo.pt', {'foo':1, 'bar':2}, request=request) + 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request + ) renderer.assert_(foo=1) renderer.assert_(bar=2) renderer.assert_(request=request) @@ -141,65 +157,81 @@ class TestingConfiguratorMixinTests(unittest.TestCase): renderer1 = config.testing_add_renderer('templates/foo.pt') renderer2 = config.testing_add_renderer('templates/bar.pt') from pyramid.testing import DummyTemplateRenderer + self.assertTrue(isinstance(renderer1, DummyTemplateRenderer)) self.assertTrue(isinstance(renderer2, DummyTemplateRenderer)) from pyramid.renderers import render_to_response + # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry render_to_response( - 'templates/foo.pt', {'foo':1, 'bar':2}, request=request) + 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request + ) renderer1.assert_(foo=1) renderer1.assert_(bar=2) renderer1.assert_(request=request) render_to_response( - 'templates/bar.pt', {'foo':1, 'bar':2}, request=request) + 'templates/bar.pt', {'foo': 1, 'bar': 2}, request=request + ) renderer2.assert_(foo=1) renderer2.assert_(bar=2) renderer2.assert_(request=request) def test_testing_add_renderer_explicitrenderer(self): config = self._makeOne(autocommit=True) - class E(Exception): pass + + class E(Exception): + pass + def renderer(kw, system): - self.assertEqual(kw, {'foo':1, 'bar':2}) + self.assertEqual(kw, {'foo': 1, 'bar': 2}) raise E + renderer = config.testing_add_renderer('templates/foo.pt', renderer) from pyramid.renderers import render_to_response + # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry try: render_to_response( - 'templates/foo.pt', {'foo':1, 'bar':2}, request=request) + 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request + ) except E: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_testing_add_template(self): config = self._makeOne(autocommit=True) renderer = config.testing_add_template('templates/foo.pt') from pyramid.testing import DummyTemplateRenderer + self.assertTrue(isinstance(renderer, DummyTemplateRenderer)) from pyramid.renderers import render_to_response + # must provide request to pass in registry (this is a functest) request = DummyRequest() request.registry = config.registry - render_to_response('templates/foo.pt', dict(foo=1, bar=2), - request=request) + render_to_response( + 'templates/foo.pt', dict(foo=1, bar=2), request=request + ) renderer.assert_(foo=1) renderer.assert_(bar=2) renderer.assert_(request=request) + from zope.interface import implementer + + @implementer(IDummy) class DummyEvent: pass + class DummyRequest(AuthenticationAPIMixin, AuthorizationAPIMixin): def __init__(self, environ=None): if environ is None: environ = {} self.environ = environ - diff --git a/tests/test_config/test_tweens.py b/tests/test_config/test_tweens.py index 25615c699..ed41c9a43 100644 --- a/tests/test_config/test_tweens.py +++ b/tests/test_config/test_tweens.py @@ -5,81 +5,101 @@ from . import dummy_tween_factory2 from pyramid.exceptions import ConfigurationConflictError + class TestTweensConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config def test_add_tweens_names_distinct(self): from pyramid.interfaces import ITweens from pyramid.tweens import excview_tween_factory - def factory1(handler, registry): return handler - def factory2(handler, registry): return handler + + def factory1(handler, registry): + return handler + + def factory2(handler, registry): + return handler + config = self._makeOne() - config.add_tween( - 'tests.test_config.dummy_tween_factory') - config.add_tween( - 'tests.test_config.dummy_tween_factory2') + config.add_tween('tests.test_config.dummy_tween_factory') + config.add_tween('tests.test_config.dummy_tween_factory2') config.commit() tweens = config.registry.queryUtility(ITweens) implicit = tweens.implicit() self.assertEqual( implicit, [ - ('tests.test_config.dummy_tween_factory2', - dummy_tween_factory2), - ('tests.test_config.dummy_tween_factory', - dummy_tween_factory), - ('pyramid.tweens.excview_tween_factory', - excview_tween_factory), - ] - ) + ( + 'tests.test_config.dummy_tween_factory2', + dummy_tween_factory2, + ), + ('tests.test_config.dummy_tween_factory', dummy_tween_factory), + ( + 'pyramid.tweens.excview_tween_factory', + excview_tween_factory, + ), + ], + ) def test_add_tweens_names_with_underover(self): from pyramid.interfaces import ITweens from pyramid.tweens import excview_tween_factory from pyramid.tweens import MAIN + config = self._makeOne() - config.add_tween( - 'tests.test_config.dummy_tween_factory', - over=MAIN) + config.add_tween('tests.test_config.dummy_tween_factory', over=MAIN) config.add_tween( 'tests.test_config.dummy_tween_factory2', over=MAIN, - under='tests.test_config.dummy_tween_factory') + under='tests.test_config.dummy_tween_factory', + ) config.commit() tweens = config.registry.queryUtility(ITweens) implicit = tweens.implicit() self.assertEqual( implicit, [ - ('pyramid.tweens.excview_tween_factory', excview_tween_factory), - ('tests.test_config.dummy_tween_factory', - dummy_tween_factory), - ('tests.test_config.dummy_tween_factory2', - dummy_tween_factory2), - ]) + ( + 'pyramid.tweens.excview_tween_factory', + excview_tween_factory, + ), + ('tests.test_config.dummy_tween_factory', dummy_tween_factory), + ( + 'tests.test_config.dummy_tween_factory2', + dummy_tween_factory2, + ), + ], + ) def test_add_tweens_names_with_under_nonstringoriter(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() self.assertRaises( - ConfigurationError, config.add_tween, + ConfigurationError, + config.add_tween, 'tests.test_config.dummy_tween_factory', - under=False) + under=False, + ) def test_add_tweens_names_with_over_nonstringoriter(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne() self.assertRaises( - ConfigurationError, config.add_tween, + ConfigurationError, + config.add_tween, 'tests.test_config.dummy_tween_factory', - over=False) + over=False, + ) def test_add_tween_dottedname(self): from pyramid.interfaces import ITweens from pyramid.tweens import excview_tween_factory + config = self._makeOne() config.add_tween('tests.test_config.dummy_tween_factory') config.commit() @@ -87,15 +107,20 @@ class TestTweensConfiguratorMixin(unittest.TestCase): self.assertEqual( tweens.implicit(), [ - ('tests.test_config.dummy_tween_factory', - dummy_tween_factory), - ('pyramid.tweens.excview_tween_factory', - excview_tween_factory), - ]) + ('tests.test_config.dummy_tween_factory', dummy_tween_factory), + ( + 'pyramid.tweens.excview_tween_factory', + excview_tween_factory, + ), + ], + ) def test_add_tween_instance(self): from pyramid.exceptions import ConfigurationError - class ATween(object): pass + + class ATween(object): + pass + atween = ATween() config = self._makeOne() self.assertRaises(ConfigurationError, config.add_tween, atween) @@ -103,19 +128,23 @@ class TestTweensConfiguratorMixin(unittest.TestCase): def test_add_tween_unsuitable(self): from pyramid.exceptions import ConfigurationError import tests.test_config + config = self._makeOne() - self.assertRaises(ConfigurationError, config.add_tween, - tests.test_config) + self.assertRaises( + ConfigurationError, config.add_tween, tests.test_config + ) def test_add_tween_name_ingress(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import INGRESS + config = self._makeOne() self.assertRaises(ConfigurationError, config.add_tween, INGRESS) def test_add_tween_name_main(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import MAIN + config = self._makeOne() self.assertRaises(ConfigurationError, config.add_tween, MAIN) @@ -128,79 +157,97 @@ class TestTweensConfiguratorMixin(unittest.TestCase): def test_add_tween_over_ingress(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import INGRESS + config = self._makeOne() self.assertRaises( ConfigurationError, config.add_tween, 'tests.test_config.dummy_tween_factory', - over=INGRESS) + over=INGRESS, + ) def test_add_tween_over_ingress_iterable(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import INGRESS + config = self._makeOne() self.assertRaises( ConfigurationError, config.add_tween, 'tests.test_config.dummy_tween_factory', - over=('a', INGRESS)) + over=('a', INGRESS), + ) def test_add_tween_under_main(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import MAIN + config = self._makeOne() self.assertRaises( ConfigurationError, config.add_tween, 'tests.test_config.dummy_tween_factory', - under=MAIN) + under=MAIN, + ) def test_add_tween_under_main_iterable(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import MAIN + config = self._makeOne() self.assertRaises( ConfigurationError, config.add_tween, 'tests.test_config.dummy_tween_factory', - under=('a', MAIN)) + under=('a', MAIN), + ) + class TestTweens(unittest.TestCase): def _makeOne(self): from pyramid.config.tweens import Tweens + return Tweens() def test_add_explicit(self): tweens = self._makeOne() tweens.add_explicit('name', 'factory') - self.assertEqual(tweens.explicit, [('name', 'factory')]) + self.assertEqual(tweens.explicit, [('name', 'factory')]) tweens.add_explicit('name2', 'factory2') - self.assertEqual(tweens.explicit, [('name', 'factory'), - ('name2', 'factory2')]) + self.assertEqual( + tweens.explicit, [('name', 'factory'), ('name2', 'factory2')] + ) def test_add_implicit(self): tweens = self._makeOne() tweens.add_implicit('name', 'factory') tweens.add_implicit('name2', 'factory2') - self.assertEqual(tweens.sorter.sorted(), - [('name2', 'factory2'), - ('name', 'factory')]) + self.assertEqual( + tweens.sorter.sorted(), + [('name2', 'factory2'), ('name', 'factory')], + ) def test___call___explicit(self): tweens = self._makeOne() + def factory1(handler, registry): return handler + def factory2(handler, registry): return '123' + tweens.explicit = [('name', factory1), ('name', factory2)] self.assertEqual(tweens(None, None), '123') def test___call___implicit(self): tweens = self._makeOne() + def factory1(handler, registry): return handler + def factory2(handler, registry): return '123' + tweens.add_implicit('name2', factory2) tweens.add_implicit('name1', factory1) self.assertEqual(tweens(None, None), '123') @@ -209,45 +256,46 @@ class TestTweens(unittest.TestCase): tweens = self._makeOne() tweens.add_implicit('name1', 'factory1') tweens.add_implicit('name2', 'factory2') - self.assertEqual(tweens.implicit(), - [ - ('name2', 'factory2'), - ('name1', 'factory1'), - ]) + self.assertEqual( + tweens.implicit(), [('name2', 'factory2'), ('name1', 'factory1')] + ) def test_implicit_ordering_2(self): from pyramid.tweens import MAIN + tweens = self._makeOne() tweens.add_implicit('name1', 'factory1') tweens.add_implicit('name2', 'factory2', over=MAIN) - self.assertEqual(tweens.implicit(), - [ - ('name1', 'factory1'), - ('name2', 'factory2'), - ]) + self.assertEqual( + tweens.implicit(), [('name1', 'factory1'), ('name2', 'factory2')] + ) def test_implicit_ordering_3(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('auth', 'auth_factory', under='browserid') - add('dbt', 'dbt_factory') + add('dbt', 'dbt_factory') add('retry', 'retry_factory', over='txnmgr', under='exceptionview') add('browserid', 'browserid_factory') add('txnmgr', 'txnmgr_factory', under='exceptionview') add('exceptionview', 'excview_factory', over=MAIN) - self.assertEqual(tweens.implicit(), - [ - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('dbt', 'dbt_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ]) + self.assertEqual( + tweens.implicit(), + [ + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('dbt', 'dbt_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ], + ) def test_implicit_ordering_4(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) @@ -255,19 +303,22 @@ class TestTweens(unittest.TestCase): add('retry', 'retry_factory', over='txnmgr', under='exceptionview') add('browserid', 'browserid_factory') add('txnmgr', 'txnmgr_factory', under='exceptionview') - add('dbt', 'dbt_factory') - self.assertEqual(tweens.implicit(), - [ - ('dbt', 'dbt_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + tweens.implicit(), + [ + ('dbt', 'dbt_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ], + ) def test_implicit_ordering_5(self): from pyramid.tweens import MAIN, INGRESS + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) @@ -275,19 +326,22 @@ class TestTweens(unittest.TestCase): add('retry', 'retry_factory', over='txnmgr', under='exceptionview') add('browserid', 'browserid_factory', under=INGRESS) add('txnmgr', 'txnmgr_factory', under='exceptionview', over=MAIN) - add('dbt', 'dbt_factory') - self.assertEqual(tweens.implicit(), - [ - ('dbt', 'dbt_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + tweens.implicit(), + [ + ('dbt', 'dbt_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ], + ) def test_implicit_ordering_missing_over_partial(self): from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() add = tweens.add_implicit add('dbt', 'dbt_factory') @@ -298,6 +352,7 @@ class TestTweens(unittest.TestCase): def test_implicit_ordering_missing_under_partial(self): from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() add = tweens.add_implicit add('dbt', 'dbt_factory') @@ -308,6 +363,7 @@ class TestTweens(unittest.TestCase): def test_implicit_ordering_missing_over_and_under_partials(self): from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() add = tweens.add_implicit add('dbt', 'dbt_factory') @@ -318,72 +374,89 @@ class TestTweens(unittest.TestCase): def test_implicit_ordering_missing_over_partial_with_fallback(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) add('auth', 'auth_factory', under='browserid') - add('retry', 'retry_factory', over=('txnmgr',MAIN), - under='exceptionview') + add( + 'retry', + 'retry_factory', + over=('txnmgr', MAIN), + under='exceptionview', + ) add('browserid', 'browserid_factory') - add('dbt', 'dbt_factory') - self.assertEqual(tweens.implicit(), - [ - ('dbt', 'dbt_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + tweens.implicit(), + [ + ('dbt', 'dbt_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_implicit_ordering_missing_under_partial_with_fallback(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) - add('auth', 'auth_factory', under=('txnmgr','browserid')) + add('auth', 'auth_factory', under=('txnmgr', 'browserid')) add('retry', 'retry_factory', under='exceptionview') add('browserid', 'browserid_factory') add('dbt', 'dbt_factory') - self.assertEqual(tweens.implicit(), - [ - ('dbt', 'dbt_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + self.assertEqual( + tweens.implicit(), + [ + ('dbt', 'dbt_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_implicit_ordering_with_partial_fallbacks(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=('wontbethere', MAIN)) add('retry', 'retry_factory', under='exceptionview') add('browserid', 'browserid_factory', over=('wont2', 'exceptionview')) - self.assertEqual(tweens.implicit(), - [ - ('browserid', 'browserid_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + self.assertEqual( + tweens.implicit(), + [ + ('browserid', 'browserid_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_implicit_ordering_with_multiple_matching_fallbacks(self): from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) add('retry', 'retry_factory', under='exceptionview') add('browserid', 'browserid_factory', over=('retry', 'exceptionview')) - self.assertEqual(tweens.implicit(), - [ - ('browserid', 'browserid_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + self.assertEqual( + tweens.implicit(), + [ + ('browserid', 'browserid_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_implicit_ordering_with_missing_fallbacks(self): from pyramid.exceptions import ConfigurationError from pyramid.tweens import MAIN + tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) @@ -393,6 +466,7 @@ class TestTweens(unittest.TestCase): def test_implicit_ordering_conflict_direct(self): from pyramid.exceptions import CyclicDependencyError + tweens = self._makeOne() add = tweens.add_implicit add('browserid', 'browserid_factory') @@ -401,10 +475,10 @@ class TestTweens(unittest.TestCase): def test_implicit_ordering_conflict_indirect(self): from pyramid.exceptions import CyclicDependencyError + tweens = self._makeOne() add = tweens.add_implicit add('browserid', 'browserid_factory') add('auth', 'auth_factory', over='browserid') add('dbt', 'dbt_factory', under='browserid', over='auth') self.assertRaises(CyclicDependencyError, tweens.implicit) - diff --git a/tests/test_config/test_util.py b/tests/test_config/test_util.py index 540f3d14c..a56c00082 100644 --- a/tests/test_config/test_util.py +++ b/tests/test_config/test_util.py @@ -2,9 +2,11 @@ import unittest from pyramid.compat import text_ + class TestActionInfo(unittest.TestCase): def _getTargetClass(self): from pyramid.config.util import ActionInfo + return ActionInfo def _makeOne(self, filename, lineno, function, linerepr): @@ -13,11 +15,13 @@ class TestActionInfo(unittest.TestCase): def test_class_conforms(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IActionInfo + verifyClass(IActionInfo, self._getTargetClass()) def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IActionInfo + verifyObject(IActionInfo, self._makeOne('f', 0, 'f', 'f')) def test_ctor(self): @@ -29,15 +33,16 @@ class TestActionInfo(unittest.TestCase): def test___str__(self): inst = self._makeOne('filename', 0, 'function', ' linerepr ') - self.assertEqual(str(inst), - "Line 0 of file filename:\n linerepr ") + self.assertEqual( + str(inst), "Line 0 of file filename:\n linerepr " + ) class TestPredicateList(unittest.TestCase): - def _makeOne(self): from pyramid.config.util import PredicateList from pyramid import predicates + inst = PredicateList() for name, factory in ( ('xhr', predicates.XHRPredicate), @@ -51,7 +56,7 @@ class TestPredicateList(unittest.TestCase): ('match_param', predicates.MatchParamPredicate), ('custom', predicates.CustomPredicate), ('traverse', predicates.TraversePredicate), - ): + ): inst.add(name, factory) return inst @@ -67,6 +72,7 @@ class TestPredicateList(unittest.TestCase): def test_ordering_number_of_predicates(self): from pyramid.config.util import predvalseq + order1, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -78,7 +84,7 @@ class TestPredicateList(unittest.TestCase): containment='containment', request_type='request_type', custom=predvalseq([DummyCustomPredicate()]), - ) + ) order2, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -90,7 +96,7 @@ class TestPredicateList(unittest.TestCase): containment='containment', request_type='request_type', custom=predvalseq([DummyCustomPredicate()]), - ) + ) order3, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -101,7 +107,7 @@ class TestPredicateList(unittest.TestCase): accept='accept', containment='containment', request_type='request_type', - ) + ) order4, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -111,7 +117,7 @@ class TestPredicateList(unittest.TestCase): header='header', accept='accept', containment='containment', - ) + ) order5, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -120,7 +126,7 @@ class TestPredicateList(unittest.TestCase): match_param='foo=bar', header='header', accept='accept', - ) + ) order6, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -128,34 +134,28 @@ class TestPredicateList(unittest.TestCase): request_param='param', match_param='foo=bar', header='header', - ) + ) order7, _, _ = self._callFUT( xhr='xhr', request_method='request_method', path_info='path_info', request_param='param', match_param='foo=bar', - ) + ) order8, _, _ = self._callFUT( xhr='xhr', request_method='request_method', path_info='path_info', request_param='param', - ) + ) order9, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - path_info='path_info', - ) + xhr='xhr', request_method='request_method', path_info='path_info' + ) order10, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - ) - order11, _, _ = self._callFUT( - xhr='xhr', - ) - order12, _, _ = self._callFUT( - ) + xhr='xhr', request_method='request_method' + ) + order11, _, _ = self._callFUT(xhr='xhr') + order12, _, _ = self._callFUT() self.assertEqual(order1, order2) self.assertTrue(order3 > order2) self.assertTrue(order4 > order3) @@ -170,36 +170,19 @@ class TestPredicateList(unittest.TestCase): def test_ordering_importance_of_predicates(self): from pyramid.config.util import predvalseq - order1, _, _ = self._callFUT( - xhr='xhr', - ) - order2, _, _ = self._callFUT( - request_method='request_method', - ) - order3, _, _ = self._callFUT( - path_info='path_info', - ) - order4, _, _ = self._callFUT( - request_param='param', - ) - order5, _, _ = self._callFUT( - header='header', - ) - order6, _, _ = self._callFUT( - accept='accept', - ) - order7, _, _ = self._callFUT( - containment='containment', - ) - order8, _, _ = self._callFUT( - request_type='request_type', - ) - order9, _, _ = self._callFUT( - match_param='foo=bar', - ) + + order1, _, _ = self._callFUT(xhr='xhr') + order2, _, _ = self._callFUT(request_method='request_method') + order3, _, _ = self._callFUT(path_info='path_info') + order4, _, _ = self._callFUT(request_param='param') + order5, _, _ = self._callFUT(header='header') + order6, _, _ = self._callFUT(accept='accept') + order7, _, _ = self._callFUT(containment='containment') + order8, _, _ = self._callFUT(request_type='request_type') + order9, _, _ = self._callFUT(match_param='foo=bar') order10, _, _ = self._callFUT( - custom=predvalseq([DummyCustomPredicate()]), - ) + custom=predvalseq([DummyCustomPredicate()]) + ) self.assertTrue(order1 > order2) self.assertTrue(order2 > order3) self.assertTrue(order3 > order4) @@ -212,53 +195,50 @@ class TestPredicateList(unittest.TestCase): def test_ordering_importance_and_number(self): from pyramid.config.util import predvalseq + order1, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - ) + xhr='xhr', request_method='request_method' + ) order2, _, _ = self._callFUT( - custom=predvalseq([DummyCustomPredicate()]), - ) + custom=predvalseq([DummyCustomPredicate()]) + ) self.assertTrue(order1 < order2) order1, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - ) + xhr='xhr', request_method='request_method' + ) order2, _, _ = self._callFUT( request_method='request_method', custom=predvalseq([DummyCustomPredicate()]), - ) + ) self.assertTrue(order1 > order2) order1, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - path_info='path_info', - ) + xhr='xhr', request_method='request_method', path_info='path_info' + ) order2, _, _ = self._callFUT( request_method='request_method', custom=predvalseq([DummyCustomPredicate()]), - ) + ) self.assertTrue(order1 < order2) order1, _, _ = self._callFUT( - xhr='xhr', - request_method='request_method', - path_info='path_info', - ) + xhr='xhr', request_method='request_method', path_info='path_info' + ) order2, _, _ = self._callFUT( xhr='xhr', request_method='request_method', custom=predvalseq([DummyCustomPredicate()]), - ) + ) self.assertTrue(order1 > order2) def test_different_custom_predicates_with_same_hash(self): from pyramid.config.util import predvalseq + class PredicateWithHash(object): def __hash__(self): return 1 + a = PredicateWithHash() b = PredicateWithHash() _, _, a_phash = self._callFUT(custom=predvalseq([a])) @@ -269,57 +249,71 @@ class TestPredicateList(unittest.TestCase): order, predicates, phash = self._callFUT(traverse='/1/:a/:b') self.assertEqual(len(predicates), 1) pred = predicates[0] - info = {'traverse':'abc'} + info = {'traverse': 'abc'} request = DummyRequest() result = pred(info, request) self.assertEqual(result, True) - self.assertEqual(info, {'traverse':'abc'}) + self.assertEqual(info, {'traverse': 'abc'}) def test_traverse_matches(self): order, predicates, phash = self._callFUT(traverse='/1/:a/:b') self.assertEqual(len(predicates), 1) pred = predicates[0] - info = {'match':{'a':'a', 'b':'b'}} + info = {'match': {'a': 'a', 'b': 'b'}} request = DummyRequest() result = pred(info, request) self.assertEqual(result, True) - self.assertEqual(info, {'match': - {'a':'a', 'b':'b', 'traverse':('1', 'a', 'b')}}) + self.assertEqual( + info, {'match': {'a': 'a', 'b': 'b', 'traverse': ('1', 'a', 'b')}} + ) def test_traverse_matches_with_highorder_chars(self): order, predicates, phash = self._callFUT( - traverse=text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8')) + traverse=text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8') + ) self.assertEqual(len(predicates), 1) pred = predicates[0] - info = {'match':{'x':text_(b'Qu\xc3\xa9bec', 'utf-8')}} + info = {'match': {'x': text_(b'Qu\xc3\xa9bec', 'utf-8')}} request = DummyRequest() result = pred(info, request) self.assertEqual(result, True) self.assertEqual( info['match']['traverse'], - (text_(b'La Pe\xc3\xb1a', 'utf-8'), - text_(b'Qu\xc3\xa9bec', 'utf-8')) - ) + ( + text_(b'La Pe\xc3\xb1a', 'utf-8'), + text_(b'Qu\xc3\xa9bec', 'utf-8'), + ), + ) def test_custom_predicates_can_affect_traversal(self): from pyramid.config.util import predvalseq + def custom(info, request): m = info['match'] m['dummy'] = 'foo' return True + _, predicates, _ = self._callFUT( - custom=predvalseq([custom]), - traverse='/1/:dummy/:a') + custom=predvalseq([custom]), traverse='/1/:dummy/:a' + ) self.assertEqual(len(predicates), 2) - info = {'match':{'a':'a'}} + info = {'match': {'a': 'a'}} request = DummyRequest() self.assertTrue(all([p(info, request) for p in predicates])) - self.assertEqual(info, {'match': - {'a':'a', 'dummy':'foo', - 'traverse':('1', 'foo', 'a')}}) + self.assertEqual( + info, + { + 'match': { + 'a': 'a', + 'dummy': 'foo', + 'traverse': ('1', 'foo', 'a'), + } + }, + ) def test_predicate_text_is_correct(self): from pyramid.config.util import predvalseq + _, predicates, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -336,10 +330,12 @@ class TestPredicateList(unittest.TestCase): DummyCustomPredicate.classmethod_predicate_no_text, ] ), - match_param='foo=bar') + match_param='foo=bar', + ) self.assertEqual(predicates[0].text(), 'xhr = True') - self.assertEqual(predicates[1].text(), - "request_method = request_method") + self.assertEqual( + predicates[1].text(), "request_method = request_method" + ) self.assertEqual(predicates[2].text(), 'path_info = path_info') self.assertEqual(predicates[3].text(), 'request_param param') self.assertEqual(predicates[4].text(), 'header header') @@ -354,25 +350,25 @@ class TestPredicateList(unittest.TestCase): def test_match_param_from_string(self): _, predicates, _ = self._callFUT(match_param='foo=bar') request = DummyRequest() - request.matchdict = {'foo':'bar', 'baz':'bum'} + request.matchdict = {'foo': 'bar', 'baz': 'bum'} self.assertTrue(predicates[0](Dummy(), request)) def test_match_param_from_string_fails(self): _, predicates, _ = self._callFUT(match_param='foo=bar') request = DummyRequest() - request.matchdict = {'foo':'bum', 'baz':'bum'} + request.matchdict = {'foo': 'bum', 'baz': 'bum'} self.assertFalse(predicates[0](Dummy(), request)) def test_match_param_from_dict(self): - _, predicates, _ = self._callFUT(match_param=('foo=bar','baz=bum')) + _, predicates, _ = self._callFUT(match_param=('foo=bar', 'baz=bum')) request = DummyRequest() - request.matchdict = {'foo':'bar', 'baz':'bum'} + request.matchdict = {'foo': 'bar', 'baz': 'bum'} self.assertTrue(predicates[0](Dummy(), request)) def test_match_param_from_dict_fails(self): - _, predicates, _ = self._callFUT(match_param=('foo=bar','baz=bum')) + _, predicates, _ = self._callFUT(match_param=('foo=bar', 'baz=bum')) request = DummyRequest() - request.matchdict = {'foo':'bar', 'baz':'foo'} + request.matchdict = {'foo': 'bar', 'baz': 'foo'} self.assertFalse(predicates[0](Dummy(), request)) def test_request_method_sequence(self): @@ -386,20 +382,22 @@ class TestPredicateList(unittest.TestCase): self.assertFalse(predicates[0](Dummy(), request)) def test_request_method_ordering_hashes_same(self): - hash1, _, __= self._callFUT(request_method=('GET', 'HEAD')) - hash2, _, __= self._callFUT(request_method=('HEAD', 'GET')) + hash1, _, __ = self._callFUT(request_method=('GET', 'HEAD')) + hash2, _, __ = self._callFUT(request_method=('HEAD', 'GET')) self.assertEqual(hash1, hash2) - hash1, _, __= self._callFUT(request_method=('GET',)) - hash2, _, __= self._callFUT(request_method='GET') + hash1, _, __ = self._callFUT(request_method=('GET',)) + hash2, _, __ = self._callFUT(request_method='GET') self.assertEqual(hash1, hash2) def test_unknown_predicate(self): from pyramid.exceptions import ConfigurationError + self.assertRaises(ConfigurationError, self._callFUT, unknown=1) def test_predicate_close_matches(self): from pyramid.exceptions import ConfigurationError - with self.assertRaises(ConfigurationError) as context: + + with self.assertRaises(ConfigurationError) as context: self._callFUT(method='GET') expected_msg = ( "Unknown predicate values: {'method': 'GET'} " @@ -410,81 +408,111 @@ class TestPredicateList(unittest.TestCase): def test_notted(self): from pyramid.config import not_ from pyramid.testing import DummyRequest + request = DummyRequest() _, predicates, _ = self._callFUT( - xhr='xhr', - request_method=not_('POST'), - header=not_('header'), - ) + xhr='xhr', request_method=not_('POST'), header=not_('header') + ) self.assertEqual(predicates[0].text(), 'xhr = True') - self.assertEqual(predicates[1].text(), - "!request_method = POST") + self.assertEqual(predicates[1].text(), "!request_method = POST") self.assertEqual(predicates[2].text(), '!header header') self.assertEqual(predicates[1](None, request), True) self.assertEqual(predicates[2](None, request), True) + class TestDeprecatedPredicates(unittest.TestCase): def test_it(self): import warnings + with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always') from pyramid.config.predicates import XHRPredicate + self.assertEqual(len(w), 1) + class Test_sort_accept_offers(unittest.TestCase): def _callFUT(self, offers, order=None): from pyramid.config.util import sort_accept_offers + return sort_accept_offers(offers, order) def test_default_specificities(self): result = self._callFUT(['text/html', 'text/html;charset=utf8']) - self.assertEqual(result, [ - 'text/html;charset=utf8', 'text/html', - ]) + self.assertEqual(result, ['text/html;charset=utf8', 'text/html']) def test_specific_type_order(self): result = self._callFUT( - ['text/html', 'application/json', 'text/html;charset=utf8', 'text/plain'], + [ + 'text/html', + 'application/json', + 'text/html;charset=utf8', + 'text/plain', + ], ['application/json', 'text/html'], ) - self.assertEqual(result, [ - 'application/json', 'text/html;charset=utf8', 'text/html', 'text/plain', - ]) + self.assertEqual( + result, + [ + 'application/json', + 'text/html;charset=utf8', + 'text/html', + 'text/plain', + ], + ) def test_params_order(self): result = self._callFUT( - ['text/html;charset=utf8', 'text/html;charset=latin1', 'text/html;foo=bar'], + [ + 'text/html;charset=utf8', + 'text/html;charset=latin1', + 'text/html;foo=bar', + ], ['text/html;charset=latin1', 'text/html;charset=utf8'], ) - self.assertEqual(result, [ - 'text/html;charset=latin1', 'text/html;charset=utf8', 'text/html;foo=bar', - ]) + self.assertEqual( + result, + [ + 'text/html;charset=latin1', + 'text/html;charset=utf8', + 'text/html;foo=bar', + ], + ) def test_params_inherit_type_prefs(self): result = self._callFUT( ['text/html;charset=utf8', 'text/plain;charset=latin1'], ['text/plain', 'text/html'], ) - self.assertEqual(result, ['text/plain;charset=latin1', 'text/html;charset=utf8']) + self.assertEqual( + result, ['text/plain;charset=latin1', 'text/html;charset=utf8'] + ) + class DummyCustomPredicate(object): def __init__(self): self.__text__ = 'custom predicate' - def classmethod_predicate(*args): pass + def classmethod_predicate(*args): + pass + classmethod_predicate.__text__ = 'classmethod predicate' classmethod_predicate = classmethod(classmethod_predicate) @classmethod - def classmethod_predicate_no_text(*args): pass # pragma: no cover + def classmethod_predicate_no_text(*args): + pass # pragma: no cover + class Dummy(object): def __init__(self, **kw): self.__dict__.update(**kw) + class DummyRequest: subpath = () matchdict = None + def __init__(self, environ=None): if environ is None: environ = {} @@ -492,6 +520,7 @@ class DummyRequest: self.params = {} self.cookies = {} + class DummyConfigurator(object): def maybe_dotted(self, thing): return thing diff --git a/tests/test_config/test_views.py b/tests/test_config/test_views.py index 1af3f66bc..9b2a306f6 100644 --- a/tests/test_config/test_views.py +++ b/tests/test_config/test_views.py @@ -6,28 +6,34 @@ from . import IDummy from . import dummy_view -from pyramid.compat import ( - im_func, - text_, - ) +from pyramid.compat import im_func, text_ from pyramid.exceptions import ConfigurationError from pyramid.exceptions import ConfigurationExecutionError from pyramid.exceptions import ConfigurationConflictError + class TestViewsConfigurationMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) config.set_default_csrf_options(require_csrf=False) return config - def _getViewCallable(self, config, ctx_iface=None, exc_iface=None, - request_iface=None, name=''): + def _getViewCallable( + self, + config, + ctx_iface=None, + exc_iface=None, + request_iface=None, + name='', + ): from zope.interface import Interface from pyramid.interfaces import IRequest from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + if exc_iface: classifier = IExceptionViewClassifier ctx_iface = exc_iface @@ -38,16 +44,22 @@ class TestViewsConfigurationMixin(unittest.TestCase): if request_iface is None: request_iface = IRequest return config.registry.adapters.lookup( - (classifier, request_iface, ctx_iface), IView, name=name, - default=None) + (classifier, request_iface, ctx_iface), + IView, + name=name, + default=None, + ) def _registerRenderer(self, config, name='.txt'): from pyramid.interfaces import IRendererFactory + class Renderer: def __init__(self, info): self.__class__.info = info + def __call__(self, *arg): return b'Hello!' + config.registry.registerUtility(Renderer, IRendererFactory, name=name) return Renderer @@ -58,15 +70,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): def _assertNotFound(self, wrapper, *arg): from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, wrapper, *arg) def _getRouteRequestIface(self, config, name): from pyramid.interfaces import IRouteRequest + iface = config.registry.getUtility(IRouteRequest, name) return iface def _assertRoute(self, config, name, path, num_predicates=0): from pyramid.interfaces import IRoutesMapper + mapper = config.registry.getUtility(IRoutesMapper) routes = mapper.get_routes() route = routes[0] @@ -83,18 +98,29 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_type_and_route_name(self): config = self._makeOne(autocommit=True) view = lambda *arg: 'OK' - self.assertRaises(ConfigurationError, config.add_view, view, '', None, - None, True, True) + self.assertRaises( + ConfigurationError, + config.add_view, + view, + '', + None, + None, + True, + True, + ) def test_add_view_with_request_type(self): from pyramid.renderers import null_renderer from zope.interface import directlyProvides from pyramid.interfaces import IRequest + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, - request_type='pyramid.interfaces.IRequest', - renderer=null_renderer) + config.add_view( + view=view, + request_type='pyramid.interfaces.IRequest', + renderer=null_renderer, + ) wrapper = self._getViewCallable(config) request = DummyRequest() self._assertNotFound(wrapper, None, request) @@ -122,8 +148,9 @@ class TestViewsConfigurationMixin(unittest.TestCase): introspector = DummyIntrospector() config.introspector = introspector config.add_view(renderer='dummy.pt') - self.assertFalse(('renderer factories', '.pt') in - introspector.related[-1]) + self.assertFalse( + ('renderer factories', '.pt') in introspector.related[-1] + ) view = self._getViewCallable(config) self.assertRaises(ValueError, view, None, None) @@ -131,37 +158,45 @@ class TestViewsConfigurationMixin(unittest.TestCase): config = self._makeOne(autocommit=True) introspector = DummyIntrospector(True) config.introspector = introspector + def dummy_factory(helper): return lambda val, system_vals: 'Hello!' + config.add_renderer('.pt', dummy_factory) config.add_view(renderer='dummy.pt') self.assertTrue( - ('renderer factories', '.pt') in introspector.related[-1]) + ('renderer factories', '.pt') in introspector.related[-1] + ) view = self._getViewCallable(config) self.assertTrue(b'Hello!' in view(None, None).body) def test_add_view_wrapped_view_is_decorated(self): - def view(request): # request-only wrapper + def view(request): # request-only wrapper """ """ + config = self._makeOne(autocommit=True) config.add_view(view=view) wrapper = self._getViewCallable(config) self.assertEqual(wrapper.__module__, view.__module__) self.assertEqual(wrapper.__name__, view.__name__) self.assertEqual(wrapper.__doc__, view.__doc__) - self.assertEqual(wrapper.__discriminator__(None, None).resolve()[0], - 'view') + self.assertEqual( + wrapper.__discriminator__(None, None).resolve()[0], 'view' + ) def test_add_view_view_callable_dottedname(self): from pyramid.renderers import null_renderer + config = self._makeOne(autocommit=True) - config.add_view(view='tests.test_config.dummy_view', - renderer=null_renderer) + config.add_view( + view='tests.test_config.dummy_view', renderer=null_renderer + ) wrapper = self._getViewCallable(config) self.assertEqual(wrapper(None, None), 'OK') def test_add_view_with_function_callable(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) @@ -171,8 +206,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_function_callable_requestonly(self): from pyramid.renderers import null_renderer + def view(request): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) @@ -181,6 +218,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_name(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, name='abc', renderer=null_renderer) @@ -190,6 +228,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_name_unicode(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) name = text_(b'La Pe\xc3\xb1a', 'utf-8') @@ -200,16 +239,21 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_decorator(self): from pyramid.renderers import null_renderer + def view(request): """ ABC """ return 'OK' + def view_wrapper(fn): def inner(context, request): return fn(context, request) + return inner + config = self._makeOne(autocommit=True) - config.add_view(view=view, decorator=view_wrapper, - renderer=null_renderer) + config.add_view( + view=view, decorator=view_wrapper, renderer=null_renderer + ) wrapper = self._getViewCallable(config) self.assertFalse(wrapper is view) self.assertEqual(wrapper.__doc__, view.__doc__) @@ -218,20 +262,29 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_decorator_tuple(self): from pyramid.renderers import null_renderer + def view(request): """ ABC """ return 'OK' + def view_wrapper1(fn): def inner(context, request): return 'wrapped1' + fn(context, request) + return inner + def view_wrapper2(fn): def inner(context, request): return 'wrapped2' + fn(context, request) + return inner + config = self._makeOne(autocommit=True) - config.add_view(view=view, decorator=(view_wrapper2, view_wrapper1), - renderer=null_renderer) + config.add_view( + view=view, + decorator=(view_wrapper2, view_wrapper1), + renderer=null_renderer, + ) wrapper = self._getViewCallable(config) self.assertFalse(wrapper is view) self.assertEqual(wrapper.__doc__, view.__doc__) @@ -241,12 +294,15 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_http_cache(self): import datetime from pyramid.response import Response + response = Response('OK') + def view(request): """ ABC """ return response + config = self._makeOne(autocommit=True) - config.add_view(view=view, http_cache=(86400, {'public':True})) + config.add_view(view=view, http_cache=(86400, {'public': True})) wrapper = self._getViewCallable(config) self.assertFalse(wrapper is view) self.assertEqual(wrapper.__doc__, view.__doc__) @@ -261,10 +317,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_instance(self): from pyramid.renderers import null_renderer + class AView: def __call__(self, context, request): """ """ return 'OK' + view = AView() config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) @@ -274,11 +332,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_instancemethod(self): from pyramid.renderers import null_renderer + class View: def index(self, context, request): return 'OK' + view = View() - config=self._makeOne(autocommit=True) + config = self._makeOne(autocommit=True) config.add_view(view=view.index, renderer=null_renderer) wrapper = self._getViewCallable(config) result = wrapper(None, None) @@ -286,11 +346,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_instancemethod_requestonly(self): from pyramid.renderers import null_renderer + class View: def index(self, request): return 'OK' + view = View() - config=self._makeOne(autocommit=True) + config = self._makeOne(autocommit=True) config.add_view(view=view.index, renderer=null_renderer) wrapper = self._getViewCallable(config) result = wrapper(None, None) @@ -298,10 +360,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_instance_requestonly(self): from pyramid.renderers import null_renderer + class AView: def __call__(self, request): """ """ return 'OK' + view = AView() config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) @@ -311,6 +375,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_oldstyle_class(self): from pyramid.renderers import null_renderer + class view: def __init__(self, context, request): self.context = context @@ -318,6 +383,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) @@ -328,12 +394,14 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_as_oldstyle_class_requestonly(self): from pyramid.renderers import null_renderer + class view: def __init__(self, request): self.request = request def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) @@ -346,9 +414,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_context_as_class(self): from pyramid.renderers import null_renderer from zope.interface import implementedBy + view = lambda *arg: 'OK' + class Foo: pass + config = self._makeOne(autocommit=True) config.add_view(context=Foo, view=view, renderer=null_renderer) foo = implementedBy(Foo) @@ -357,6 +428,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_context_as_iface(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(context=IDummy, view=view, renderer=null_renderer) @@ -365,19 +437,25 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_context_as_dottedname(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(context='tests.test_config.IDummy', - view=view, renderer=null_renderer) + config.add_view( + context='tests.test_config.IDummy', + view=view, + renderer=null_renderer, + ) wrapper = self._getViewCallable(config, IDummy) self.assertEqual(wrapper, view) def test_add_view_for__as_dottedname(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(for_='tests.test_config.IDummy', - view=view, renderer=null_renderer) + config.add_view( + for_='tests.test_config.IDummy', view=view, renderer=null_renderer + ) wrapper = self._getViewCallable(config, IDummy) self.assertEqual(wrapper, view) @@ -385,9 +463,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): # ``for_`` is older spelling for ``context`` from pyramid.renderers import null_renderer from zope.interface import implementedBy + view = lambda *arg: 'OK' + class Foo: pass + config = self._makeOne(autocommit=True) config.add_view(for_=Foo, view=view, renderer=null_renderer) foo = implementedBy(Foo) @@ -397,6 +478,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_for_as_iface(self): # ``for_`` is older spelling for ``context`` from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(for_=IDummy, view=view, renderer=null_renderer) @@ -406,12 +488,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_context_trumps_for(self): # ``for_`` is older spelling for ``context`` from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) + class Foo: pass - config.add_view(context=IDummy, for_=Foo, view=view, - renderer=null_renderer) + + config.add_view( + context=IDummy, for_=Foo, view=view, renderer=null_renderer + ) wrapper = self._getViewCallable(config, IDummy) self.assertEqual(wrapper, view) @@ -421,13 +507,17 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.interfaces import ISecuredView from pyramid.interfaces import IViewClassifier + view = lambda *arg: 'OK' view.__call_permissive__ = view config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) wrapper = config.registry.adapters.lookup( (IViewClassifier, IRequest, Interface), - ISecuredView, name='', default=None) + ISecuredView, + name='', + default=None, + ) self.assertEqual(wrapper, view) def test_add_view_exception_register_secured_view(self): @@ -436,13 +526,19 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.interfaces import IView from pyramid.interfaces import IExceptionViewClassifier + view = lambda *arg: 'OK' view.__call_permissive__ = view config = self._makeOne(autocommit=True) - config.add_view(view=view, context=RuntimeError, renderer=null_renderer) + config.add_view( + view=view, context=RuntimeError, renderer=null_renderer + ) wrapper = config.registry.adapters.lookup( (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='', default=None) + IView, + name='', + default=None, + ) self.assertEqual(wrapper, view) def test_add_view_same_phash_overrides_existing_single_view(self): @@ -453,15 +549,19 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + phash = md5() phash.update(b'xhr = True') view = lambda *arg: 'NOT OK' view.__phash__ = phash.hexdigest() config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) + def newview(context, request): return 'OK' + config.add_view(view=newview, xhr=True, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertFalse(IMultiView.providedBy(wrapper)) @@ -477,6 +577,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IMultiView + phash = md5() phash.update(b'xhr = True') view = lambda *arg: 'NOT OK' @@ -485,13 +586,22 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) + def newview(context, request): return 'OK' - config.add_view(view=newview, xhr=True, context=RuntimeError, - renderer=null_renderer) + + config.add_view( + view=newview, + xhr=True, + context=RuntimeError, + renderer=null_renderer, + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertFalse(IMultiView.providedBy(wrapper)) request = DummyRequest() request.is_xhr = True @@ -504,12 +614,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'NOT OK' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) + def newview(context, request): return 'OK' + config.add_view(view=newview, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertFalse(IMultiView.providedBy(wrapper)) @@ -524,18 +638,25 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'NOT OK' config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) + def newview(context, request): return 'OK' - config.add_view(view=newview, context=RuntimeError, - renderer=null_renderer) + + config.add_view( + view=newview, context=RuntimeError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertFalse(IMultiView.providedBy(wrapper)) request = DummyRequest() request.is_xhr = True @@ -549,13 +670,17 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'NOT OK' view.__phash__ = DEFAULT_PHASH config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) + def newview(context, request): return 'OK' + config.add_view(view=newview, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertFalse(IMultiView.providedBy(wrapper)) @@ -571,19 +696,26 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'NOT OK' view.__phash__ = DEFAULT_PHASH config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) + def newview(context, request): return 'OK' - config.add_view(view=newview, context=RuntimeError, - renderer=null_renderer) + + config.add_view( + view=newview, context=RuntimeError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertFalse(IMultiView.providedBy(wrapper)) request = DummyRequest() request.is_xhr = True @@ -596,11 +728,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'OK' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) @@ -614,21 +748,28 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'OK' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') - config.add_view(view=view, context=RuntimeError, - renderer=null_renderer) + IView, + name='', + ) + config.add_view( + view=view, context=RuntimeError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(wrapper)) self.assertEqual(wrapper(None, None), 'OK') @@ -639,12 +780,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import ISecuredView from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier + view = lambda *arg: 'OK' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), - ISecuredView, name='') + view, (IViewClassifier, IRequest, Interface), ISecuredView, name='' + ) config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) @@ -658,20 +800,28 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + view = lambda *arg: 'OK' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - ISecuredView, name='') + ISecuredView, + name='', + ) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - ISecuredView, name='') - config.add_view(view=view, context=RuntimeError, renderer=null_renderer) + ISecuredView, + name='', + ) + config.add_view( + view=view, context=RuntimeError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(wrapper)) self.assertEqual(wrapper(None, None), 'OK') @@ -682,13 +832,17 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier + def view(context, request): return 'OK' + def view2(context, request): return 'OK2' + config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) config.add_view(view=view2, accept='text/html', renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) @@ -701,16 +855,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_mixed_case_replaces_existing_view(self): from pyramid.renderers import null_renderer - def view(context, request): return 'OK' - def view2(context, request): return 'OK2' - def view3(context, request): return 'OK3' + + def view(context, request): + return 'OK' + + def view2(context, request): + return 'OK2' + + def view3(context, request): + return 'OK3' + config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) config.add_view(view=view2, accept='text/html', renderer=null_renderer) config.add_view(view=view3, accept='text/HTML', renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) - self.assertEqual(len(wrapper.media_views.items()),1) + self.assertEqual(len(wrapper.media_views.items()), 1) self.assertFalse('text/HTML' in wrapper.media_views) self.assertEqual(wrapper(None, None), 'OK') request = DummyRequest() @@ -719,9 +880,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_views_with_accept_multiview_replaces_existing(self): from pyramid.renderers import null_renderer - def view(context, request): return 'OK' - def view2(context, request): return 'OK2' - def view3(context, request): return 'OK3' + + def view(context, request): + return 'OK' + + def view2(context, request): + return 'OK2' + + def view3(context, request): + return 'OK3' + config = self._makeOne(autocommit=True) config.add_view(view=view, renderer=null_renderer) config.add_view(view=view2, accept='text/html', renderer=null_renderer) @@ -741,23 +909,35 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + def view(context, request): return 'OK' + def view2(context, request): return 'OK2' + config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') - config.add_view(view=view2, accept='text/html', context=RuntimeError, - renderer=null_renderer) + IView, + name='', + ) + config.add_view( + view=view2, + accept='text/html', + context=RuntimeError, + renderer=null_renderer, + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(wrapper)) self.assertEqual(len(wrapper.views), 1) self.assertEqual(len(wrapper.media_views), 1) @@ -773,15 +953,19 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier + def view(context, request): return 'OK' + def view2(context, request): return 'OK2' + view.__accept__ = 'text/html' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) config.add_view(view=view2, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) @@ -800,25 +984,34 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + def view(context, request): return 'OK' + def view2(context, request): return 'OK2' + view.__accept__ = 'text/html' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') + IView, + name='', + ) config.registry.registerAdapter( view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IView, name='') - config.add_view(view=view2, context=RuntimeError, - renderer=null_renderer) + IView, + name='', + ) + config.add_view( + view=view2, context=RuntimeError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(wrapper)) self.assertEqual(len(wrapper.views), 1) self.assertEqual(len(wrapper.media_views), 1) @@ -833,16 +1026,19 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier + view = DummyMultiView() config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), - IMultiView, name='') + view, (IViewClassifier, IRequest, Interface), IMultiView, name='' + ) view2 = lambda *arg: 'OK2' config.add_view(view=view2, renderer=null_renderer) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) - self.assertEqual([(x[0], x[2]) for x in wrapper.views], [(view2, None)]) + self.assertEqual( + [(x[0], x[2]) for x in wrapper.views], [(view2, None)] + ) self.assertEqual(wrapper(None, None), 'OK1') def test_add_view_exc_multiview_replaces_multiviews(self): @@ -852,30 +1048,42 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + hot_view = DummyMultiView() exc_view = DummyMultiView() config = self._makeOne(autocommit=True) config.registry.registerAdapter( hot_view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - IMultiView, name='') + IMultiView, + name='', + ) config.registry.registerAdapter( exc_view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IMultiView, name='') + IMultiView, + name='', + ) view2 = lambda *arg: 'OK2' - config.add_view(view=view2, context=RuntimeError, - renderer=null_renderer) + config.add_view( + view=view2, context=RuntimeError, renderer=null_renderer + ) hot_wrapper = self._getViewCallable( - config, ctx_iface=implementedBy(RuntimeError)) + config, ctx_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(hot_wrapper)) - self.assertEqual([(x[0], x[2]) for x in hot_wrapper.views], [(view2, None)]) + self.assertEqual( + [(x[0], x[2]) for x in hot_wrapper.views], [(view2, None)] + ) self.assertEqual(hot_wrapper(None, None), 'OK1') exc_wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(exc_wrapper)) - self.assertEqual([(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]) + self.assertEqual( + [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)] + ) self.assertEqual(exc_wrapper(None, None), 'OK1') def test_add_view_exc_multiview_replaces_only_exc_multiview(self): @@ -885,30 +1093,43 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + hot_view = DummyMultiView() exc_view = DummyMultiView() config = self._makeOne(autocommit=True) config.registry.registerAdapter( hot_view, (IViewClassifier, IRequest, implementedBy(RuntimeError)), - IMultiView, name='') + IMultiView, + name='', + ) config.registry.registerAdapter( exc_view, (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)), - IMultiView, name='') + IMultiView, + name='', + ) view2 = lambda *arg: 'OK2' - config.add_view(view=view2, context=RuntimeError, exception_only=True, - renderer=null_renderer) + config.add_view( + view=view2, + context=RuntimeError, + exception_only=True, + renderer=null_renderer, + ) hot_wrapper = self._getViewCallable( - config, ctx_iface=implementedBy(RuntimeError)) + config, ctx_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(hot_wrapper)) self.assertEqual(len(hot_wrapper.views), 0) self.assertEqual(hot_wrapper(None, None), 'OK1') exc_wrapper = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError)) + config, exc_iface=implementedBy(RuntimeError) + ) self.assertTrue(IMultiView.providedBy(exc_wrapper)) - self.assertEqual([(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]) + self.assertEqual( + [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)] + ) self.assertEqual(exc_wrapper(None, None), 'OK1') def test_add_view_multiview_context_superclass_then_subclass(self): @@ -918,22 +1139,28 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier + class ISuper(Interface): pass + class ISub(ISuper): pass + view = lambda *arg: 'OK' view2 = lambda *arg: 'OK2' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, ISuper), IView, name='') + view, (IViewClassifier, IRequest, ISuper), IView, name='' + ) config.add_view(view=view2, for_=ISub, renderer=null_renderer) - wrapper = self._getViewCallable(config, ctx_iface=ISuper, - request_iface=IRequest) + wrapper = self._getViewCallable( + config, ctx_iface=ISuper, request_iface=IRequest + ) self.assertFalse(IMultiView.providedBy(wrapper)) self.assertEqual(wrapper(None, None), 'OK') - wrapper = self._getViewCallable(config, ctx_iface=ISub, - request_iface=IRequest) + wrapper = self._getViewCallable( + config, ctx_iface=ISub, request_iface=IRequest + ) self.assertFalse(IMultiView.providedBy(wrapper)) self.assertEqual(wrapper(None, None), 'OK2') @@ -945,29 +1172,38 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + class Super(Exception): pass + class Sub(Super): pass + view = lambda *arg: 'OK' view2 = lambda *arg: 'OK2' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Super), IView, name='') + view, (IViewClassifier, IRequest, Super), IView, name='' + ) config.registry.registerAdapter( - view, (IExceptionViewClassifier, IRequest, Super), IView, name='') + view, (IExceptionViewClassifier, IRequest, Super), IView, name='' + ) config.add_view(view=view2, for_=Sub, renderer=null_renderer) wrapper = self._getViewCallable( - config, ctx_iface=implementedBy(Super), request_iface=IRequest) + config, ctx_iface=implementedBy(Super), request_iface=IRequest + ) wrapper_exc_view = self._getViewCallable( - config, exc_iface=implementedBy(Super), request_iface=IRequest) + config, exc_iface=implementedBy(Super), request_iface=IRequest + ) self.assertEqual(wrapper_exc_view, wrapper) self.assertFalse(IMultiView.providedBy(wrapper_exc_view)) self.assertEqual(wrapper_exc_view(None, None), 'OK') wrapper = self._getViewCallable( - config, ctx_iface=implementedBy(Sub), request_iface=IRequest) + config, ctx_iface=implementedBy(Sub), request_iface=IRequest + ) wrapper_exc_view = self._getViewCallable( - config, exc_iface=implementedBy(Sub), request_iface=IRequest) + config, exc_iface=implementedBy(Sub), request_iface=IRequest + ) self.assertEqual(wrapper_exc_view, wrapper) self.assertFalse(IMultiView.providedBy(wrapper_exc_view)) self.assertEqual(wrapper_exc_view(None, None), 'OK2') @@ -975,28 +1211,55 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_multiview_call_ordering(self): from pyramid.renderers import null_renderer as nr from zope.interface import directlyProvides - def view1(context, request): return 'view1' - def view2(context, request): return 'view2' - def view3(context, request): return 'view3' - def view4(context, request): return 'view4' - def view5(context, request): return 'view5' - def view6(context, request): return 'view6' - def view7(context, request): return 'view7' - def view8(context, request): return 'view8' + + def view1(context, request): + return 'view1' + + def view2(context, request): + return 'view2' + + def view3(context, request): + return 'view3' + + def view4(context, request): + return 'view4' + + def view5(context, request): + return 'view5' + + def view6(context, request): + return 'view6' + + def view7(context, request): + return 'view7' + + def view8(context, request): + return 'view8' + config = self._makeOne(autocommit=True) config.add_view(view=view1, renderer=nr) config.add_view(view=view2, request_method='POST', renderer=nr) - config.add_view(view=view3,request_param='param', renderer=nr) + config.add_view(view=view3, request_param='param', renderer=nr) config.add_view(view=view4, containment=IDummy, renderer=nr) - config.add_view(view=view5, request_method='POST', - request_param='param', renderer=nr) - config.add_view(view=view6, request_method='POST', containment=IDummy, - renderer=nr) - config.add_view(view=view7, request_param='param', containment=IDummy, - renderer=nr) - config.add_view(view=view8, request_method='POST',request_param='param', - containment=IDummy, renderer=nr) - + config.add_view( + view=view5, + request_method='POST', + request_param='param', + renderer=nr, + ) + config.add_view( + view=view6, request_method='POST', containment=IDummy, renderer=nr + ) + config.add_view( + view=view7, request_param='param', containment=IDummy, renderer=nr + ) + config.add_view( + view=view8, + request_method='POST', + request_param='param', + containment=IDummy, + renderer=nr, + ) wrapper = self._getViewCallable(config) @@ -1014,7 +1277,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): ctx = DummyContext() request = self._makeRequest(config) - request.params = {'param':'1'} + request.params = {'param': '1'} request.method = 'GET' self.assertEqual(wrapper(ctx, request), 'view3') @@ -1028,7 +1291,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): ctx = DummyContext() request = self._makeRequest(config) request.method = 'POST' - request.params = {'param':'1'} + request.params = {'param': '1'} self.assertEqual(wrapper(ctx, request), 'view5') ctx = DummyContext() @@ -1042,40 +1305,55 @@ class TestViewsConfigurationMixin(unittest.TestCase): directlyProvides(ctx, IDummy) request = self._makeRequest(config) request.method = 'GET' - request.params = {'param':'1'} + request.params = {'param': '1'} self.assertEqual(wrapper(ctx, request), 'view7') ctx = DummyContext() directlyProvides(ctx, IDummy) request = self._makeRequest(config) request.method = 'POST' - request.params = {'param':'1'} + request.params = {'param': '1'} self.assertEqual(wrapper(ctx, request), 'view8') def test_view_with_most_specific_predicate(self): from pyramid.renderers import null_renderer as nr from pyramid.router import Router - class OtherBase(object): pass - class Int1(object): pass - class Int2(object): pass + class OtherBase(object): + pass + + class Int1(object): + pass + + class Int2(object): + pass class Resource(OtherBase, Int1, Int2): - def __init__(self, request): pass + def __init__(self, request): + pass - def unknown(context, request): return 'unknown' - def view(context, request): return 'hello' + def unknown(context, request): + return 'unknown' + + def view(context, request): + return 'hello' config = self._makeOne(autocommit=True) config.add_route('root', '/', factory=Resource) config.add_view(unknown, route_name='root', renderer=nr) config.add_view( - view, renderer=nr, route_name='root', - context=Int1, request_method='GET' + view, + renderer=nr, + route_name='root', + context=Int1, + request_method='GET', ) config.add_view( - view=view, renderer=nr, route_name='root', - context=Int2, request_method='POST' + view=view, + renderer=nr, + route_name='root', + context=Int2, + request_method='POST', ) request = self._makeRequest(config) request.method = 'POST' @@ -1088,15 +1366,24 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.router import Router - class OtherBase(object): pass - class Int1(object): pass - class Int2(object): pass + class OtherBase(object): + pass + + class Int1(object): + pass + + class Int2(object): + pass class Resource(OtherBase, Int1, Int2): - def __init__(self, request): pass + def __init__(self, request): + pass + + def unknown(context, request): + return 'unknown' - def unknown(context, request): return 'unknown' - def view(context, request): return 'hello' + def view(context, request): + return 'hello' config = self._makeOne(autocommit=True) config.add_route('root', '/', factory=Resource) @@ -1110,12 +1397,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): ) config.add_view( - view, renderer=nr, route_name='root', - context=Int1, request_method='GET' + view, + renderer=nr, + route_name='root', + context=Int1, + request_method='GET', ) config.add_view( - view=view, renderer=nr, route_name='root', - context=Int2, request_method='POST' + view=view, + renderer=nr, + route_name='root', + context=Int2, + request_method='POST', ) request = self._makeRequest(config) request.method = 'POST' @@ -1127,16 +1420,21 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_multiview___discriminator__(self): from pyramid.renderers import null_renderer from zope.interface import Interface + class IFoo(Interface): pass + class IBar(Interface): pass + @implementer(IFoo) class Foo(object): pass + @implementer(IBar) class Bar(object): pass + foo = Foo() bar = Bar() @@ -1144,33 +1442,35 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView + view = lambda *arg: 'OK' view.__phash__ = 'abc' config = self._makeOne(autocommit=True) config.registry.registerAdapter( - view, (IViewClassifier, IRequest, Interface), IView, name='') - config.add_view(view=view, renderer=null_renderer, - containment=IFoo) - config.add_view(view=view, renderer=null_renderer, - containment=IBar) + view, (IViewClassifier, IRequest, Interface), IView, name='' + ) + config.add_view(view=view, renderer=null_renderer, containment=IFoo) + config.add_view(view=view, renderer=null_renderer, containment=IBar) wrapper = self._getViewCallable(config) self.assertTrue(IMultiView.providedBy(wrapper)) request = self._makeRequest(config) self.assertNotEqual( wrapper.__discriminator__(foo, request), wrapper.__discriminator__(bar, request), - ) + ) def test_add_view_with_template_renderer(self): from tests import test_config from pyramid.interfaces import ISettings + class view(object): def __init__(self, context, request): self.request = request self.context = context def __call__(self): - return {'a':'1'} + return {'a': '1'} + config = self._makeOne(autocommit=True) renderer = self._registerRenderer(config) fixture = 'tests.test_config:files/minimal.txt' @@ -1195,13 +1495,17 @@ class TestViewsConfigurationMixin(unittest.TestCase): self.context = context def __call__(self): - return {'a':'1'} + return {'a': '1'} + config = self._makeOne(autocommit=True) + class moo(object): def __init__(self, *arg, **kw): pass + def __call__(self, *arg, **kw): return b'moo' + config.add_renderer(None, moo) config.add_view(view=view) wrapper = self._getViewCallable(config) @@ -1212,6 +1516,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_template_renderer_no_callable(self): from tests import test_config from pyramid.interfaces import ISettings + config = self._makeOne(autocommit=True) renderer = self._registerRenderer(config) fixture = 'tests.test_config:files/minimal.txt' @@ -1232,8 +1537,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_type_as_iface(self): from pyramid.renderers import null_renderer from zope.interface import directlyProvides + def view(context, request): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(request_type=IDummy, view=view, renderer=null_renderer) wrapper = self._getViewCallable(config, None) @@ -1245,11 +1552,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_type_as_noniface(self): view = lambda *arg: 'OK' config = self._makeOne() - self.assertRaises(ConfigurationError, - config.add_view, view, '', None, None, object) + self.assertRaises( + ConfigurationError, config.add_view, view, '', None, None, object + ) def test_add_view_with_route_name(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_route('foo', '/a/b') @@ -1262,6 +1571,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_nonexistant_route_name(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne() config.add_view(view=view, route_name='foo', renderer=null_renderer) @@ -1270,28 +1580,39 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_route_name_exception(self): from pyramid.renderers import null_renderer from zope.interface import implementedBy + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_route('foo', '/a/b') - config.add_view(view=view, route_name='foo', context=RuntimeError, - renderer=null_renderer) + config.add_view( + view=view, + route_name='foo', + context=RuntimeError, + renderer=null_renderer, + ) request_iface = self._getRouteRequestIface(config, 'foo') wrapper_exc_view = self._getViewCallable( - config, exc_iface=implementedBy(RuntimeError), - request_iface=request_iface) + config, + exc_iface=implementedBy(RuntimeError), + request_iface=request_iface, + ) self.assertNotEqual(wrapper_exc_view, None) wrapper = self._getViewCallable( - config, ctx_iface=implementedBy(RuntimeError), - request_iface=request_iface) + config, + ctx_iface=implementedBy(RuntimeError), + request_iface=request_iface, + ) self.assertEqual(wrapper_exc_view, wrapper) self.assertEqual(wrapper_exc_view(None, None), 'OK') def test_add_view_with_request_method_true(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, request_method='POST', - renderer=null_renderer) + config.add_view( + view=view, request_method='POST', renderer=null_renderer + ) wrapper = self._getViewCallable(config) request = self._makeRequest(config) request.method = 'POST' @@ -1308,10 +1629,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_method_sequence_true(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, request_method=('POST', 'GET'), - renderer=null_renderer) + config.add_view( + view=view, request_method=('POST', 'GET'), renderer=null_renderer + ) wrapper = self._getViewCallable(config) request = self._makeRequest(config) request.method = 'POST' @@ -1319,12 +1642,15 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_method_sequence_conflict(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne() - config.add_view(view=view, request_method=('POST', 'GET'), - renderer=null_renderer) - config.add_view(view=view, request_method=('GET', 'POST'), - renderer=null_renderer) + config.add_view( + view=view, request_method=('POST', 'GET'), renderer=null_renderer + ) + config.add_view( + view=view, request_method=('GET', 'POST'), renderer=null_renderer + ) self.assertRaises(ConfigurationConflictError, config.commit) def test_add_view_with_request_method_sequence_false(self): @@ -1338,9 +1664,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_method_get_implies_head(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, request_method='GET', renderer=null_renderer) + config.add_view( + view=view, request_method='GET', renderer=null_renderer + ) wrapper = self._getViewCallable(config) request = self._makeRequest(config) request.method = 'HEAD' @@ -1348,12 +1677,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_param_noval_true(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, request_param='abc', renderer=null_renderer) wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.params = {'abc':''} + request.params = {'abc': ''} self.assertEqual(wrapper(None, request), 'OK') def test_add_view_with_request_param_noval_false(self): @@ -1367,13 +1697,15 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_request_param_val_true(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, request_param='abc=123', - renderer=null_renderer) + config.add_view( + view=view, request_param='abc=123', renderer=null_renderer + ) wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.params = {'abc':'123'} + request.params = {'abc': '123'} self.assertEqual(wrapper(None, request), 'OK') def test_add_view_with_request_param_val_false(self): @@ -1382,11 +1714,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.add_view(view=view, request_param='abc=123') wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.params = {'abc':''} + request.params = {'abc': ''} self._assertNotFound(wrapper, None, request) def test_add_view_with_xhr_true(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, xhr=True, renderer=null_renderer) @@ -1412,12 +1745,13 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_header_noval_match(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, header='Host', renderer=null_renderer) wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.headers = {'Host':'whatever'} + request.headers = {'Host': 'whatever'} self.assertEqual(wrapper(None, request), 'OK') def test_add_view_with_header_noval_nomatch(self): @@ -1426,17 +1760,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.add_view(view=view, header='Host') wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.headers = {'NotHost':'whatever'} + request.headers = {'NotHost': 'whatever'} self._assertNotFound(wrapper, None, request) def test_add_view_with_header_val_match(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, header=r'Host:\d', renderer=null_renderer) wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.headers = {'Host':'1'} + request.headers = {'Host': '1'} self.assertEqual(wrapper(None, request), 'OK') def test_add_view_with_header_val_nomatch(self): @@ -1445,21 +1780,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.add_view(view=view, header=r'Host:\d') wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.headers = {'Host':'abc'} + request.headers = {'Host': 'abc'} self._assertNotFound(wrapper, None, request) def test_add_view_with_header_val_missing(self): from pyramid.httpexceptions import HTTPNotFound + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, header=r'Host:\d') wrapper = self._getViewCallable(config) request = self._makeRequest(config) - request.headers = {'NoHost':'1'} + request.headers = {'NoHost': '1'} self.assertRaises(HTTPNotFound, wrapper, None, request) def test_add_view_with_accept_match(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, accept='text/xml', renderer=null_renderer) @@ -1479,6 +1816,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_range_accept_match(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, accept='text/*', renderer=null_renderer) @@ -1499,6 +1837,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_containment_true(self): from pyramid.renderers import null_renderer from zope.interface import directlyProvides + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, containment=IDummy, renderer=null_renderer) @@ -1518,12 +1857,14 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_containment_dottedname(self): from pyramid.renderers import null_renderer from zope.interface import directlyProvides + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view( view=view, containment='tests.test_config.IDummy', - renderer=null_renderer) + renderer=null_renderer, + ) wrapper = self._getViewCallable(config) context = DummyContext() directlyProvides(context, IDummy) @@ -1537,6 +1878,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_path_info_match(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_view(view=view, path_info='/foo', renderer=null_renderer) @@ -1557,6 +1899,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_check_csrf_predicates_match(self): import warnings from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) with warnings.catch_warnings(record=True) as w: @@ -1574,17 +1917,22 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_custom_predicates_match(self): import warnings from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) + def pred1(context, request): return True + def pred2(context, request): return True + predicates = (pred1, pred2) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always') - config.add_view(view=view, custom_predicates=predicates, - renderer=null_renderer) + config.add_view( + view=view, custom_predicates=predicates, renderer=null_renderer + ) self.assertEqual(len(w), 1) wrapper = self._getViewCallable(config) request = self._makeRequest(config) @@ -1592,12 +1940,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_custom_predicates_nomatch(self): import warnings + view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) + def pred1(context, request): return True + def pred2(context, request): return False + predicates = (pred1, pred2) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always') @@ -1610,17 +1962,22 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_custom_predicate_bests_standard_predicate(self): import warnings from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' view2 = lambda *arg: 'NOT OK' config = self._makeOne(autocommit=True) + def pred1(context, request): return True + with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always') - config.add_view(view=view, custom_predicates=(pred1,), - renderer=null_renderer) - config.add_view(view=view2, request_method='GET', - renderer=null_renderer) + config.add_view( + view=view, custom_predicates=(pred1,), renderer=null_renderer + ) + config.add_view( + view=view2, request_method='GET', renderer=null_renderer + ) self.assertEqual(len(w), 1) wrapper = self._getViewCallable(config) request = self._makeRequest(config) @@ -1629,13 +1986,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_custom_more_preds_first_bests_fewer_preds_last(self): from pyramid.renderers import null_renderer + view = lambda *arg: 'OK' view2 = lambda *arg: 'NOT OK' config = self._makeOne(autocommit=True) - config.add_view(view=view, request_method='GET', xhr=True, - renderer=null_renderer) - config.add_view(view=view2, request_method='GET', - renderer=null_renderer) + config.add_view( + view=view, request_method='GET', xhr=True, renderer=null_renderer + ) + config.add_view( + view=view2, request_method='GET', renderer=null_renderer + ) wrapper = self._getViewCallable(config) request = self._makeRequest(config) request.method = 'GET' @@ -1652,8 +2012,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_csrf_param(self): from pyramid.renderers import null_renderer + def view(request): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view, require_csrf='st', renderer=null_renderer) view = self._getViewCallable(config) @@ -1667,8 +2029,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_csrf_header(self): from pyramid.renderers import null_renderer + def view(request): return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view, require_csrf=True, renderer=null_renderer) view = self._getViewCallable(config) @@ -1683,7 +2047,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_missing_csrf_header(self): from pyramid.exceptions import BadCSRFToken from pyramid.renderers import null_renderer - def view(request): return 'OK' + + def view(request): + return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view, require_csrf=True, renderer=null_renderer) view = self._getViewCallable(config) @@ -1697,21 +2064,27 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_permission(self): from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' outerself = self + class DummyPolicy(object): def effective_principals(self, r): outerself.assertEqual(r, request) return ['abc'] + def permits(self, context, principals, permission): outerself.assertEqual(context, None) outerself.assertEqual(principals, ['abc']) outerself.assertEqual(permission, 'view') return True + policy = DummyPolicy() - config = self._makeOne(authorization_policy=policy, - authentication_policy=policy, - autocommit=True) + config = self._makeOne( + authorization_policy=policy, + authentication_policy=policy, + autocommit=True, + ) config.add_view(view=view1, permission='view', renderer=null_renderer) view = self._getViewCallable(config) request = self._makeRequest(config) @@ -1719,22 +2092,28 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_default_permission_no_explicit_permission(self): from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' outerself = self + class DummyPolicy(object): def effective_principals(self, r): outerself.assertEqual(r, request) return ['abc'] + def permits(self, context, principals, permission): outerself.assertEqual(context, None) outerself.assertEqual(principals, ['abc']) outerself.assertEqual(permission, 'view') return True + policy = DummyPolicy() - config = self._makeOne(authorization_policy=policy, - authentication_policy=policy, - default_permission='view', - autocommit=True) + config = self._makeOne( + authorization_policy=policy, + authentication_policy=policy, + default_permission='view', + autocommit=True, + ) config.add_view(view=view1, renderer=null_renderer) view = self._getViewCallable(config) request = self._makeRequest(config) @@ -1742,12 +2121,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_no_default_permission_no_explicit_permission(self): from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' - class DummyPolicy(object): pass # wont be called + + class DummyPolicy(object): + pass # wont be called + policy = DummyPolicy() - config = self._makeOne(authorization_policy=policy, - authentication_policy=policy, - autocommit=True) + config = self._makeOne( + authorization_policy=policy, + authentication_policy=policy, + autocommit=True, + ) config.add_view(view=view1, renderer=null_renderer) view = self._getViewCallable(config) request = self._makeRequest(config) @@ -1755,13 +2140,19 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_mapper(self): from pyramid.renderers import null_renderer + class Mapper(object): def __init__(self, **kw): self.__class__.kw = kw + def __call__(self, view): return view + config = self._makeOne(autocommit=True) - def view(context, request): return 'OK' + + def view(context, request): + return 'OK' + config.add_view(view=view, mapper=Mapper, renderer=null_renderer) view = self._getViewCallable(config) self.assertEqual(view(None, None), 'OK') @@ -1771,18 +2162,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.renderers import null_renderer from pyramid.exceptions import PredicateMismatch from zope.interface import directlyProvides + class view(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + def __init__(self, request): pass + def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) - config.add_view( - view=view, - renderer=null_renderer) + config.add_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable(config) context = DummyContext() directlyProvides(context, IDummy) @@ -1796,10 +2187,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.renderers import null_renderer from pyramid.exceptions import PredicateMismatch from zope.interface import directlyProvides + config = self._makeOne(autocommit=True) config.add_view( view='tests.test_config.test_views.DummyViewDefaultsClass', - renderer=null_renderer) + renderer=null_renderer, + ) wrapper = self._getViewCallable(config) context = DummyContext() directlyProvides(context, IDummy) @@ -1813,10 +2206,12 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.renderers import null_renderer from pyramid.exceptions import PredicateMismatch from zope.interface import directlyProvides + config = self._makeOne(autocommit=True) config.add_view( 'tests.test_config.test_views.DummyViewDefaultsClass', - renderer=null_renderer) + renderer=null_renderer, + ) wrapper = self._getViewCallable(config) context = DummyContext() directlyProvides(context, IDummy) @@ -1828,40 +2223,30 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_with_view_config_and_view_defaults_doesnt_conflict(self): from pyramid.renderers import null_renderer + class view(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + class view2(object): - __view_defaults__ = { - 'containment':'tests.test_config.IFactory' - } + __view_defaults__ = {'containment': 'tests.test_config.IFactory'} + config = self._makeOne(autocommit=False) - config.add_view( - view=view, - renderer=null_renderer) - config.add_view( - view=view2, - renderer=null_renderer) - config.commit() # does not raise + config.add_view(view=view, renderer=null_renderer) + config.add_view(view=view2, renderer=null_renderer) + config.commit() # does not raise def test_add_view_with_view_config_and_view_defaults_conflicts(self): from pyramid.renderers import null_renderer + class view(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + class view2(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + config = self._makeOne(autocommit=False) - config.add_view( - view=view, - renderer=null_renderer) - config.add_view( - view=view2, - renderer=null_renderer) + config.add_view(view=view, renderer=null_renderer) + config.add_view(view=view2, renderer=null_renderer) self.assertRaises(ConfigurationConflictError, config.commit) def test_add_view_class_method_no_attr(self): @@ -1870,8 +2255,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.exceptions import ConfigurationError config = self._makeOne(autocommit=True) + class DummyViewClass(object): - def run(self): pass + def run(self): + pass def configure_view(): config.add_view(view=DummyViewClass.run, renderer=null_renderer) @@ -1881,41 +2268,62 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_exception_only_no_regular_view(self): from zope.interface import implementedBy from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view1, context=Exception, exception_only=True, - renderer=null_renderer) - view = self._getViewCallable(config, ctx_iface=implementedBy(Exception)) + config.add_view( + view=view1, + context=Exception, + exception_only=True, + renderer=null_renderer, + ) + view = self._getViewCallable( + config, ctx_iface=implementedBy(Exception) + ) self.assertTrue(view is None) def test_add_view_exception_only(self): from zope.interface import implementedBy from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_view(view=view1, context=Exception, exception_only=True, - renderer=null_renderer) + config.add_view( + view=view1, + context=Exception, + exception_only=True, + renderer=null_renderer, + ) view = self._getViewCallable( - config, exc_iface=implementedBy(Exception)) + config, exc_iface=implementedBy(Exception) + ) self.assertEqual(view1, view) def test_add_view_exception_only_misconfiguration(self): view = lambda *arg: 'OK' config = self._makeOne(autocommit=True) + class NotAnException(object): pass + self.assertRaises( ConfigurationError, - config.add_view, view, context=NotAnException, exception_only=True) + config.add_view, + view, + context=NotAnException, + exception_only=True, + ) def test_add_exception_view(self): from zope.interface import implementedBy from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' config = self._makeOne(autocommit=True) config.add_exception_view(view=view1, renderer=null_renderer) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(Exception)) + config, exc_iface=implementedBy(Exception) + ) context = Exception() request = self._makeRequest(config) self.assertEqual(wrapper(context, request), 'OK') @@ -1923,71 +2331,86 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_exception_view_with_subclass(self): from zope.interface import implementedBy from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' config = self._makeOne(autocommit=True) - config.add_exception_view(view=view1, context=ValueError, - renderer=null_renderer) + config.add_exception_view( + view=view1, context=ValueError, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(ValueError)) + config, exc_iface=implementedBy(ValueError) + ) context = ValueError() request = self._makeRequest(config) self.assertEqual(wrapper(context, request), 'OK') def test_add_exception_view_disallows_name(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_exception_view, - context=Exception(), - name='foo') + self.assertRaises( + ConfigurationError, + config.add_exception_view, + context=Exception(), + name='foo', + ) def test_add_exception_view_disallows_permission(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_exception_view, - context=Exception(), - permission='foo') + self.assertRaises( + ConfigurationError, + config.add_exception_view, + context=Exception(), + permission='foo', + ) def test_add_exception_view_disallows_require_csrf(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_exception_view, - context=Exception(), - require_csrf=True) + self.assertRaises( + ConfigurationError, + config.add_exception_view, + context=Exception(), + require_csrf=True, + ) def test_add_exception_view_disallows_for_(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_exception_view, - context=Exception(), - for_='foo') + self.assertRaises( + ConfigurationError, + config.add_exception_view, + context=Exception(), + for_='foo', + ) def test_add_exception_view_disallows_exception_only(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_exception_view, - context=Exception(), - exception_only=True) + self.assertRaises( + ConfigurationError, + config.add_exception_view, + context=Exception(), + exception_only=True, + ) def test_add_exception_view_with_view_defaults(self): from pyramid.renderers import null_renderer from pyramid.exceptions import PredicateMismatch from zope.interface import directlyProvides from zope.interface import implementedBy + class view(object): - __view_defaults__ = { - 'containment': 'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + def __init__(self, request): pass + def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) config.add_exception_view( - view=view, - context=Exception, - renderer=null_renderer) + view=view, context=Exception, renderer=null_renderer + ) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(Exception)) + config, exc_iface=implementedBy(Exception) + ) context = DummyContext() directlyProvides(context, IDummy) request = self._makeRequest(config) @@ -1998,8 +2421,10 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_derive_view_function(self): from pyramid.renderers import null_renderer + def view(request): return 'OK' + config = self._makeOne() result = config.derive_view(view, renderer=null_renderer) self.assertFalse(result is view) @@ -2007,37 +2432,48 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_derive_view_dottedname(self): from pyramid.renderers import null_renderer + config = self._makeOne() result = config.derive_view( - 'tests.test_config.dummy_view', - renderer=null_renderer) + 'tests.test_config.dummy_view', renderer=null_renderer + ) self.assertFalse(result is dummy_view) self.assertEqual(result(None, None), 'OK') def test_derive_view_with_default_renderer_no_explicit_renderer(self): config = self._makeOne() + class moo(object): def __init__(self, view): pass + def __call__(self, *arg, **kw): return 'moo' + config.add_renderer(None, moo) config.commit() + def view(request): return 'OK' + result = config.derive_view(view) self.assertFalse(result is view) self.assertEqual(result(None, None).body, b'moo') def test_derive_view_with_default_renderer_with_explicit_renderer(self): - class moo(object): pass + class moo(object): + pass + class foo(object): def __init__(self, view): pass + def __call__(self, *arg, **kw): return b'foo' + def view(request): return 'OK' + config = self._makeOne() config.add_renderer(None, moo) config.add_renderer('foo', foo) @@ -2052,64 +2488,71 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import Interface from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier + config = self._makeOne(autocommit=True) config.add_static_view('static', 'files', renderer=null_renderer) request_type = self._getRouteRequestIface(config, '__static/') self._assertRoute(config, '__static/', 'static/*subpath') wrapped = config.registry.adapters.lookup( - (IViewClassifier, request_type, Interface), IView, name='') + (IViewClassifier, request_type, Interface), IView, name='' + ) from pyramid.request import Request + request = Request.blank('/static/minimal.txt') - request.subpath = ('minimal.txt', ) + request.subpath = ('minimal.txt',) result = wrapped(None, request) self.assertEqual(result.status, '200 OK') self.assertTrue(result.body.startswith(b'<div')) def test_add_static_view_package_relative(self): from pyramid.interfaces import IStaticURLInfo + info = DummyStaticURLInfo() config = self._makeOne(autocommit=True) config.registry.registerUtility(info, IStaticURLInfo) - config.add_static_view('static', - 'tests.test_config:files') + config.add_static_view('static', 'tests.test_config:files') self.assertEqual( - info.added, - [(config, 'static', 'tests.test_config:files', {})]) + info.added, [(config, 'static', 'tests.test_config:files', {})] + ) def test_add_static_view_package_here_relative(self): from pyramid.interfaces import IStaticURLInfo + info = DummyStaticURLInfo() config = self._makeOne(autocommit=True) config.registry.registerUtility(info, IStaticURLInfo) config.add_static_view('static', 'files') self.assertEqual( - info.added, - [(config, 'static', 'tests.test_config:files', {})]) + info.added, [(config, 'static', 'tests.test_config:files', {})] + ) def test_add_static_view_absolute(self): import os from pyramid.interfaces import IStaticURLInfo + info = DummyStaticURLInfo() config = self._makeOne(autocommit=True) config.registry.registerUtility(info, IStaticURLInfo) here = os.path.dirname(__file__) static_path = os.path.join(here, 'files') config.add_static_view('static', static_path) - self.assertEqual(info.added, - [(config, 'static', static_path, {})]) + self.assertEqual(info.added, [(config, 'static', static_path, {})]) def test_add_forbidden_view(self): from pyramid.renderers import null_renderer from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPForbidden + config = self._makeOne(autocommit=True) view = lambda *arg: 'OK' config.add_forbidden_view(view, renderer=null_renderer) request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPForbidden), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPForbidden), + request_iface=IRequest, + ) result = view(None, request) self.assertEqual(result, 'OK') @@ -2117,19 +2560,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPForbidden + config = self._makeOne(autocommit=True) config.setup_registry() config.add_forbidden_view() request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPForbidden), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPForbidden), + request_iface=IRequest, + ) context = HTTPForbidden() result = view(context, request) self.assertEqual(result, context) def test_add_forbidden_view_allows_other_predicates(self): from pyramid.renderers import null_renderer + config = self._makeOne(autocommit=True) # doesnt blow up config.add_view_predicate('dummy', DummyPredicate) @@ -2137,28 +2584,33 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_forbidden_view_disallows_name(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_forbidden_view, name='foo') + self.assertRaises( + ConfigurationError, config.add_forbidden_view, name='foo' + ) def test_add_forbidden_view_disallows_permission(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_forbidden_view, permission='foo') + self.assertRaises( + ConfigurationError, config.add_forbidden_view, permission='foo' + ) def test_add_forbidden_view_disallows_require_csrf(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_forbidden_view, require_csrf=True) + self.assertRaises( + ConfigurationError, config.add_forbidden_view, require_csrf=True + ) def test_add_forbidden_view_disallows_context(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_forbidden_view, context='foo') + self.assertRaises( + ConfigurationError, config.add_forbidden_view, context='foo' + ) def test_add_forbidden_view_disallows_for_(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_forbidden_view, for_='foo') + self.assertRaises( + ConfigurationError, config.add_forbidden_view, for_='foo' + ) def test_add_forbidden_view_with_view_defaults(self): from pyramid.interfaces import IRequest @@ -2167,21 +2619,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.httpexceptions import HTTPForbidden from zope.interface import directlyProvides from zope.interface import implementedBy + class view(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + def __init__(self, request): pass + def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) - config.add_forbidden_view( - view=view, - renderer=null_renderer) + config.add_forbidden_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(HTTPForbidden), - request_iface=IRequest) + config, + exc_iface=implementedBy(HTTPForbidden), + request_iface=IRequest, + ) context = DummyContext() directlyProvides(context, IDummy) request = self._makeRequest(config) @@ -2195,13 +2649,16 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPNotFound + config = self._makeOne(autocommit=True) view = lambda *arg: arg config.add_notfound_view(view, renderer=null_renderer) request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) result = view(None, request) self.assertEqual(result, (None, request)) @@ -2209,19 +2666,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPNotFound + config = self._makeOne(autocommit=True) config.setup_registry() config.add_notfound_view() request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) context = HTTPNotFound() result = view(context, request) self.assertEqual(result, context) def test_add_notfound_view_allows_other_predicates(self): from pyramid.renderers import null_renderer + config = self._makeOne(autocommit=True) # doesnt blow up config.add_view_predicate('dummy', DummyPredicate) @@ -2229,28 +2690,33 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_notfound_view_disallows_name(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_notfound_view, name='foo') + self.assertRaises( + ConfigurationError, config.add_notfound_view, name='foo' + ) def test_add_notfound_view_disallows_permission(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_notfound_view, permission='foo') + self.assertRaises( + ConfigurationError, config.add_notfound_view, permission='foo' + ) def test_add_notfound_view_disallows_require_csrf(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_notfound_view, require_csrf=True) + self.assertRaises( + ConfigurationError, config.add_notfound_view, require_csrf=True + ) def test_add_notfound_view_disallows_context(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_notfound_view, context='foo') + self.assertRaises( + ConfigurationError, config.add_notfound_view, context='foo' + ) def test_add_notfound_view_disallows_for_(self): config = self._makeOne(autocommit=True) - self.assertRaises(ConfigurationError, - config.add_notfound_view, for_='foo') + self.assertRaises( + ConfigurationError, config.add_notfound_view, for_='foo' + ) def test_add_notfound_view_append_slash(self): from pyramid.response import Response @@ -2258,17 +2724,25 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPTemporaryRedirect, HTTPNotFound + config = self._makeOne(autocommit=True) config.add_route('foo', '/foo/') - def view(request): return Response('OK') - config.add_notfound_view(view, renderer=null_renderer,append_slash=True) + + def view(request): + return Response('OK') + + config.add_notfound_view( + view, renderer=null_renderer, append_slash=True + ) request = self._makeRequest(config) request.environ['PATH_INFO'] = '/foo' request.query_string = 'a=1&b=2' request.path = '/scriptname/foo' - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) result = view(None, request) self.assertTrue(isinstance(result, HTTPTemporaryRedirect)) self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2') @@ -2279,19 +2753,25 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound + config = self._makeOne(autocommit=True) config.add_route('foo', '/foo/') - def view(request): return Response('OK') + + def view(request): + return Response('OK') + config.add_notfound_view( - view, renderer=null_renderer,append_slash=HTTPMovedPermanently + view, renderer=null_renderer, append_slash=HTTPMovedPermanently ) request = self._makeRequest(config) request.environ['PATH_INFO'] = '/foo' request.query_string = 'a=1&b=2' request.path = '/scriptname/foo' - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) result = view(None, request) self.assertTrue(isinstance(result, HTTPMovedPermanently)) self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2') @@ -2303,21 +2783,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.httpexceptions import HTTPNotFound from zope.interface import directlyProvides from zope.interface import implementedBy + class view(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + def __init__(self, request): pass + def __call__(self): return 'OK' + config = self._makeOne(autocommit=True) - config.add_notfound_view( - view=view, - renderer=null_renderer) + config.add_notfound_view(view=view, renderer=null_renderer) wrapper = self._getViewCallable( - config, exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) context = DummyContext() directlyProvides(context, IDummy) request = self._makeRequest(config) @@ -2329,6 +2811,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): # Since Python 3 has to be all cool and fancy and different... def _assertBody(self, response, value): from pyramid.compat import text_type + if isinstance(value, text_type): # pragma: no cover self.assertEqual(response.text, value) else: # pragma: no cover @@ -2338,16 +2821,17 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPNotFound + config = self._makeOne(autocommit=True) view = lambda *arg: {} config.introspection = False - config.add_notfound_view( - view, - renderer='json') + config.add_notfound_view(view, renderer='json') request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPNotFound), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPNotFound), + request_iface=IRequest, + ) result = view(None, request) self._assertBody(result, '{}') @@ -2355,21 +2839,23 @@ class TestViewsConfigurationMixin(unittest.TestCase): from zope.interface import implementedBy from pyramid.interfaces import IRequest from pyramid.httpexceptions import HTTPForbidden + config = self._makeOne(autocommit=True) view = lambda *arg: {} config.introspection = False - config.add_forbidden_view( - view, - renderer='json') + config.add_forbidden_view(view, renderer='json') request = self._makeRequest(config) - view = self._getViewCallable(config, - exc_iface=implementedBy(HTTPForbidden), - request_iface=IRequest) + view = self._getViewCallable( + config, + exc_iface=implementedBy(HTTPForbidden), + request_iface=IRequest, + ) result = view(None, request) self._assertBody(result, '{}') def test_set_view_mapper(self): from pyramid.interfaces import IViewMapperFactory + config = self._makeOne(autocommit=True) mapper = object() config.set_view_mapper(mapper) @@ -2378,15 +2864,18 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_set_view_mapper_dottedname(self): from pyramid.interfaces import IViewMapperFactory + config = self._makeOne(autocommit=True) config.set_view_mapper('tests.test_config') result = config.registry.getUtility(IViewMapperFactory) from tests import test_config + self.assertEqual(result, test_config) def test_add_normal_and_exception_view_intr_derived_callable(self): from pyramid.renderers import null_renderer from pyramid.exceptions import BadCSRFToken + config = self._makeOne(autocommit=True) introspector = DummyIntrospector() config.introspector = introspector @@ -2410,27 +2899,33 @@ class TestViewsConfigurationMixin(unittest.TestCase): def test_add_view_does_not_accept_iterable_accept(self): from pyramid.exceptions import ConfigurationError + config = self._makeOne(autocommit=True) self.assertRaises( - ConfigurationError, config.add_view, accept=['image/*', 'text/*'], + ConfigurationError, config.add_view, accept=['image/*', 'text/*'] ) def test_default_accept_view_order(self): from pyramid.interfaces import IAcceptOrder + config = self._makeOne(autocommit=True) order = config.registry.getUtility(IAcceptOrder) result = [v for _, v in order.sorted()] - self.assertEqual(result, [ - 'text/html', - 'application/xhtml+xml', - 'application/xml', - 'text/xml', - 'text/plain', - 'application/json', - ]) + self.assertEqual( + result, + [ + 'text/html', + 'application/xhtml+xml', + 'application/xml', + 'text/xml', + 'text/plain', + 'application/json', + ], + ) def test_add_accept_view_order_override(self): from pyramid.interfaces import IAcceptOrder + config = self._makeOne(autocommit=False) config.add_accept_view_order( 'text/html', @@ -2440,57 +2935,75 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.commit() order = config.registry.getUtility(IAcceptOrder) result = [v for _, v in order.sorted()] - self.assertEqual(result, [ - 'application/xhtml+xml', - 'application/xml', - 'text/html', - 'text/xml', - 'text/plain', - 'application/json', - ]) + self.assertEqual( + result, + [ + 'application/xhtml+xml', + 'application/xml', + 'text/html', + 'text/xml', + 'text/plain', + 'application/json', + ], + ) def test_add_accept_view_order_throws_on_wildcard(self): config = self._makeOne(autocommit=True) - self.assertRaises( - ValueError, config.add_accept_view_order, '*/*', - ) + self.assertRaises(ValueError, config.add_accept_view_order, '*/*') def test_add_accept_view_order_throws_on_type_mismatch(self): config = self._makeOne(autocommit=True) self.assertRaises( - ValueError, config.add_accept_view_order, - 'text/*', weighs_more_than='text/html', + ValueError, + config.add_accept_view_order, + 'text/*', + weighs_more_than='text/html', ) self.assertRaises( - ValueError, config.add_accept_view_order, - 'text/html', weighs_less_than='application/*', + ValueError, + config.add_accept_view_order, + 'text/html', + weighs_less_than='application/*', ) self.assertRaises( - ConfigurationError, config.add_accept_view_order, - 'text/html', weighs_more_than='text/html;charset=utf8', + ConfigurationError, + config.add_accept_view_order, + 'text/html', + weighs_more_than='text/html;charset=utf8', ) self.assertRaises( - ConfigurationError, config.add_accept_view_order, + ConfigurationError, + config.add_accept_view_order, 'text/html;charset=utf8', weighs_more_than='text/plain;charset=utf8', ) + class Test_runtime_exc_view(unittest.TestCase): def _makeOne(self, view1, view2): from pyramid.config.views import runtime_exc_view + return runtime_exc_view(view1, view2) def test_call(self): - def view1(context, request): return 'OK' - def view2(context, request): raise AssertionError + def view1(context, request): + return 'OK' + + def view2(context, request): + raise AssertionError + result_view = self._makeOne(view1, view2) request = DummyRequest() result = result_view(None, request) self.assertEqual(result, 'OK') def test_call_dispatches_on_exception(self): - def view1(context, request): raise AssertionError - def view2(context, request): return 'OK' + def view1(context, request): + raise AssertionError + + def view2(context, request): + return 'OK' + result_view = self._makeOne(view1, view2) request = DummyRequest() request.exception = Exception() @@ -2498,10 +3011,17 @@ class Test_runtime_exc_view(unittest.TestCase): self.assertEqual(result, 'OK') def test_permitted(self): - def errfn(context, request): raise AssertionError - def view1(context, request): raise AssertionError + def errfn(context, request): + raise AssertionError + + def view1(context, request): + raise AssertionError + view1.__permitted__ = lambda c, r: 'OK' - def view2(context, request): raise AssertionError + + def view2(context, request): + raise AssertionError + view2.__permitted__ = errfn result_view = self._makeOne(view1, view2) request = DummyRequest() @@ -2509,10 +3029,17 @@ class Test_runtime_exc_view(unittest.TestCase): self.assertEqual(result, 'OK') def test_permitted_dispatches_on_exception(self): - def errfn(context, request): raise AssertionError - def view1(context, request): raise AssertionError + def errfn(context, request): + raise AssertionError + + def view1(context, request): + raise AssertionError + view1.__permitted__ = errfn - def view2(context, request): raise AssertionError + + def view2(context, request): + raise AssertionError + view2.__permitted__ = lambda c, r: 'OK' result_view = self._makeOne(view1, view2) request = DummyRequest() @@ -2520,50 +3047,67 @@ class Test_runtime_exc_view(unittest.TestCase): result = result_view.__permitted__(None, request) self.assertEqual(result, 'OK') + class Test_requestonly(unittest.TestCase): def _callFUT(self, view, attr=None): from pyramid.config.views import requestonly + return requestonly(view, attr=attr) def test_defaults(self): - def aview(request, a=1, b=2): pass + def aview(request, a=1, b=2): + pass + self.assertTrue(self._callFUT(aview)) def test_otherattr(self): class AView(object): - def __init__(self, request, a=1, b=2): pass - def bleh(self): pass + def __init__(self, request, a=1, b=2): + pass + + def bleh(self): + pass + self.assertTrue(self._callFUT(AView, 'bleh')) + class Test_isexception(unittest.TestCase): def _callFUT(self, ob): from pyramid.config.views import isexception + return isexception(ob) def test_is_exception_instance(self): class E(Exception): pass + e = E() self.assertEqual(self._callFUT(e), True) def test_is_exception_class(self): class E(Exception): pass + self.assertEqual(self._callFUT(E), True) def test_is_IException(self): from pyramid.interfaces import IException + self.assertEqual(self._callFUT(IException), True) def test_is_IException_subinterface(self): from pyramid.interfaces import IException + class ISubException(IException): pass + self.assertEqual(self._callFUT(ISubException), True) + class TestMultiView(unittest.TestCase): def _getTargetClass(self): from pyramid.config.views import MultiView + return MultiView def _makeOne(self, name='name'): @@ -2572,11 +3116,13 @@ class TestMultiView(unittest.TestCase): def test_class_implements_ISecuredView(self): from zope.interface.verify import verifyClass from pyramid.interfaces import ISecuredView + verifyClass(ISecuredView, self._getTargetClass()) def test_instance_implements_ISecuredView(self): from zope.interface.verify import verifyObject from pyramid.interfaces import ISecuredView + verifyObject(ISecuredView, self._makeOne()) def test_add(self): @@ -2588,15 +3134,19 @@ class TestMultiView(unittest.TestCase): mv.add('view3', 100, accept='text/html') self.assertEqual(mv.media_views['text/html'], [(100, 'view3', None)]) mv.add('view4', 99, 'abc', accept='text/html') - self.assertEqual(mv.media_views['text/html'], - [(99, 'view4', 'abc'), (100, 'view3', None)]) + self.assertEqual( + mv.media_views['text/html'], + [(99, 'view4', 'abc'), (100, 'view3', None)], + ) mv.add('view5', 100, accept='text/xml') self.assertEqual(mv.media_views['text/xml'], [(100, 'view5', None)]) self.assertEqual(set(mv.accepts), set(['text/xml', 'text/html'])) self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)]) mv.add('view6', 98, accept='text/*') - self.assertEqual(mv.views, [ - (98, 'view6', None), (99, 'view2', None), (100, 'view', None)]) + self.assertEqual( + mv.views, + [(98, 'view6', None), (99, 'view2', None), (100, 'view', None)], + ) def test_add_with_phash(self): mv = self._makeOne() @@ -2605,43 +3155,64 @@ class TestMultiView(unittest.TestCase): mv.add('view', 100, phash='abc') self.assertEqual(mv.views, [(100, 'view', 'abc')]) mv.add('view', 100, phash='def') - self.assertEqual(mv.views, [(100, 'view', 'abc'), - (100, 'view', 'def')]) + self.assertEqual( + mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')] + ) mv.add('view', 100, phash='abc') - self.assertEqual(mv.views, [(100, 'view', 'abc'), - (100, 'view', 'def')]) + self.assertEqual( + mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')] + ) def test_add_with_phash_override_accept(self): mv = self._makeOne() - def view1(): pass - def view2(): pass - def view3(): pass + + def view1(): + pass + + def view2(): + pass + + def view3(): + pass + mv.add(view1, 100, accept='text/html', phash='abc') mv.add(view2, 100, accept='text/html', phash='abc') mv.add(view3, 99, accept='text/html', phash='def') - self.assertEqual(mv.media_views['text/html'], - [(99, view3, 'def'), (100, view2, 'abc')]) + self.assertEqual( + mv.media_views['text/html'], + [(99, view3, 'def'), (100, view2, 'abc')], + ) def test_add_with_phash_override_accept2(self): mv = self._makeOne() - def view1(): pass - def view2(): pass - def view3(): pass + + def view1(): + pass + + def view2(): + pass + + def view3(): + pass + mv.add(view1, 100, accept='text/html', phash='abc') mv.add(view2, 100, accept='text/html', phash='def') mv.add(view3, 99, accept='text/html', phash='ghi') - self.assertEqual(mv.media_views['text/html'], - [(99, view3, 'ghi'), - (100, view1, 'abc'), - (100, view2, 'def')] - ) + self.assertEqual( + mv.media_views['text/html'], + [(99, view3, 'ghi'), (100, view1, 'abc'), (100, view2, 'def')], + ) def test_multiple_with_functions_as_views(self): # this failed on py3 at one point, because functions aren't orderable # and we were sorting the views via a plain sort() rather than # sort(key=itemgetter(0)). - def view1(request): pass - def view2(request): pass + def view1(request): + pass + + def view2(request): + pass + mv = self._makeOne() mv.add(view1, 100, None) self.assertEqual(mv.views, [(100, view1, None)]) @@ -2682,6 +3253,7 @@ class TestMultiView(unittest.TestCase): def test_match_not_found(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() context = DummyContext() request = DummyRequest() @@ -2689,9 +3261,12 @@ class TestMultiView(unittest.TestCase): def test_match_predicate_fails(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() + def view(context, request): """ """ + view.__predicated__ = lambda *arg: False mv.views = [(100, view, None)] context = DummyContext() @@ -2700,8 +3275,10 @@ class TestMultiView(unittest.TestCase): def test_match_predicate_succeeds(self): mv = self._makeOne() + def view(context, request): """ """ + view.__predicated__ = lambda *arg: True mv.views = [(100, view, None)] context = DummyContext() @@ -2711,6 +3288,7 @@ class TestMultiView(unittest.TestCase): def test_permitted_no_views(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() context = DummyContext() request = DummyRequest() @@ -2718,17 +3296,22 @@ class TestMultiView(unittest.TestCase): def test_permitted_no_match_with__permitted__(self): mv = self._makeOne() + def view(context, request): """ """ + mv.views = [(100, view, None)] self.assertEqual(mv.__permitted__(None, None), True) def test_permitted(self): mv = self._makeOne() + def view(context, request): """ """ + def permitted(context, request): return False + view.__permitted__ = permitted mv.views = [(100, view, None)] context = DummyContext() @@ -2738,6 +3321,7 @@ class TestMultiView(unittest.TestCase): def test__call__not_found(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() context = DummyContext() request = DummyRequest() @@ -2745,29 +3329,37 @@ class TestMultiView(unittest.TestCase): def test___call__intermediate_not_found(self): from pyramid.exceptions import PredicateMismatch + mv = self._makeOne() context = DummyContext() request = DummyRequest() request.view_name = '' expected_response = DummyResponse() + def view1(context, request): raise PredicateMismatch + def view2(context, request): return expected_response + mv.views = [(100, view1, None), (99, view2, None)] response = mv(context, request) self.assertEqual(response, expected_response) def test___call__raise_not_found_isnt_interpreted_as_pred_mismatch(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() context = DummyContext() request = DummyRequest() request.view_name = '' + def view1(context, request): - raise HTTPNotFound + raise HTTPNotFound + def view2(context, request): """ """ + mv.views = [(100, view1, None), (99, view2, None)] self.assertRaises(HTTPNotFound, mv, context, request) @@ -2777,14 +3369,17 @@ class TestMultiView(unittest.TestCase): request = DummyRequest() request.view_name = '' expected_response = DummyResponse() + def view(context, request): return expected_response + mv.views = [(100, view, None)] response = mv(context, request) self.assertEqual(response, expected_response) def test__call_permissive__not_found(self): from pyramid.httpexceptions import HTTPNotFound + mv = self._makeOne() context = DummyContext() request = DummyRequest() @@ -2796,10 +3391,13 @@ class TestMultiView(unittest.TestCase): request = DummyRequest() request.view_name = '' expected_response = DummyResponse() + def view(context, request): """ """ + def permissive(context, request): return expected_response + view.__call_permissive__ = permissive mv.views = [(100, view, None)] response = mv.__call_permissive__(context, request) @@ -2811,8 +3409,10 @@ class TestMultiView(unittest.TestCase): request = DummyRequest() request.view_name = '' expected_response = DummyResponse() + def view(context, request): return expected_response + mv.views = [(100, view, None)] response = mv.__call_permissive__(context, request) self.assertEqual(response, expected_response) @@ -2823,8 +3423,10 @@ class TestMultiView(unittest.TestCase): request = DummyRequest() request.accept = DummyAccept('text/html', 'text/xml') expected_response = DummyResponse() + def view(context, request): return expected_response + mv.views = [(100, None)] mv.media_views['text/xml'] = [(100, view, None)] mv.accepts = ['text/xml'] @@ -2837,8 +3439,10 @@ class TestMultiView(unittest.TestCase): request = DummyRequest() request.accept = DummyAccept('text/plain', 'text/html') expected_response = DummyResponse() + def view(context, request): return expected_response + mv.views = [(100, view, None)] mv.media_views['text/xml'] = [(100, None, None)] mv.accepts = ['text/xml'] @@ -2846,7 +3450,6 @@ class TestMultiView(unittest.TestCase): self.assertEqual(response, expected_response) - class TestDefaultViewMapper(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -2858,6 +3461,7 @@ class TestDefaultViewMapper(unittest.TestCase): def _makeOne(self, **kw): from pyramid.config.views import DefaultViewMapper + kw['registry'] = self.registry return DefaultViewMapper(**kw) @@ -2869,6 +3473,7 @@ class TestDefaultViewMapper(unittest.TestCase): def test_view_as_function_context_and_request(self): def view(context, request): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertTrue(result is view) @@ -2878,6 +3483,7 @@ class TestDefaultViewMapper(unittest.TestCase): def test__view_as_function_with_attr(self): def view(context, request): """ """ + mapper = self._makeOne(attr='__name__') result = mapper(view) self.assertFalse(result is view) @@ -2887,6 +3493,7 @@ class TestDefaultViewMapper(unittest.TestCase): def test_view_as_function_requestonly(self): def view(request): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertFalse(result is view) @@ -2896,6 +3503,7 @@ class TestDefaultViewMapper(unittest.TestCase): def test_view_as_function_requestonly_with_attr(self): def view(request): """ """ + mapper = self._makeOne(attr='__name__') result = mapper(view) self.assertFalse(result is view) @@ -2906,8 +3514,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view(object): def __init__(self, context, request): pass + def __call__(self): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertFalse(result is view) @@ -2918,8 +3528,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view(object): def __init__(self, context, request): pass + def index(self): return 'OK' + mapper = self._makeOne(attr='index') result = mapper(view) self.assertFalse(result is view) @@ -2930,8 +3542,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view(object): def __init__(self, request): pass + def __call__(self): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertFalse(result is view) @@ -2942,8 +3556,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view(object): def __init__(self, request): pass + def index(self): return 'OK' + mapper = self._makeOne(attr='index') result = mapper(view) self.assertFalse(result is view) @@ -2954,8 +3570,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view: def __init__(self, context, request): pass + def __call__(self): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertFalse(result is view) @@ -2966,8 +3584,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view: def __init__(self, context, request): pass + def index(self): return 'OK' + mapper = self._makeOne(attr='index') result = mapper(view) self.assertFalse(result is view) @@ -2978,8 +3598,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view: def __init__(self, request): pass + def __call__(self): return 'OK' + mapper = self._makeOne() result = mapper(view) self.assertFalse(result is view) @@ -2990,8 +3612,10 @@ class TestDefaultViewMapper(unittest.TestCase): class view: def __init__(self, request): pass + def index(self): return 'OK' + mapper = self._makeOne(attr='index') result = mapper(view) self.assertFalse(result is view) @@ -3002,6 +3626,7 @@ class TestDefaultViewMapper(unittest.TestCase): class View: def __call__(self, context, request): return 'OK' + view = View() mapper = self._makeOne() result = mapper(view) @@ -3013,6 +3638,7 @@ class TestDefaultViewMapper(unittest.TestCase): class View: def index(self, context, request): return 'OK' + view = View() mapper = self._makeOne(attr='index') result = mapper(view) @@ -3024,6 +3650,7 @@ class TestDefaultViewMapper(unittest.TestCase): class View: def __call__(self, request): return 'OK' + view = View() mapper = self._makeOne() result = mapper(view) @@ -3035,6 +3662,7 @@ class TestDefaultViewMapper(unittest.TestCase): class View: def index(self, request): return 'OK' + view = View() mapper = self._makeOne(attr='index') result = mapper(view) @@ -3042,27 +3670,36 @@ class TestDefaultViewMapper(unittest.TestCase): request = self._makeRequest() self.assertEqual(result(None, request), 'OK') + class Test_preserve_view_attrs(unittest.TestCase): def _callFUT(self, view, wrapped_view): from pyramid.config.views import preserve_view_attrs + return preserve_view_attrs(view, wrapped_view) def test_it_same(self): def view(context, request): """ """ + result = self._callFUT(view, view) self.assertTrue(result is view) def test_it_view_is_None(self): def view(context, request): """ """ + result = self._callFUT(None, view) self.assertTrue(result is view) def test_it_different_with_existing_original_view(self): - def view1(context, request): pass + def view1(context, request): + pass + view1.__original_view__ = 'abc' - def view2(context, request): pass + + def view2(context, request): + pass + result = self._callFUT(view1, view2) self.assertEqual(result.__original_view__, 'abc') self.assertFalse(result is view1) @@ -3070,28 +3707,40 @@ class Test_preserve_view_attrs(unittest.TestCase): def test_it_different(self): class DummyView1: """ 1 """ + __name__ = '1' __module__ = '1' + def __call__(self, context, request): """ """ + def __call_permissive__(self, context, request): """ """ + def __predicated__(self, context, request): """ """ + def __permitted__(self, context, request): """ """ + class DummyView2: """ 2 """ + __name__ = '2' __module__ = '2' + def __call__(self, context, request): """ """ + def __call_permissive__(self, context, request): """ """ + def __predicated__(self, context, request): """ """ + def __permitted__(self, context, request): """ """ + view1 = DummyView1() view2 = DummyView2() result = self._callFUT(view2, view1) @@ -3100,17 +3749,24 @@ class Test_preserve_view_attrs(unittest.TestCase): self.assertTrue(view1.__doc__ is view2.__doc__) self.assertTrue(view1.__module__ is view2.__module__) self.assertTrue(view1.__name__ is view2.__name__) - self.assertTrue(getattr(view1.__call_permissive__, im_func) is - getattr(view2.__call_permissive__, im_func)) - self.assertTrue(getattr(view1.__permitted__, im_func) is - getattr(view2.__permitted__, im_func)) - self.assertTrue(getattr(view1.__predicated__, im_func) is - getattr(view2.__predicated__, im_func)) + self.assertTrue( + getattr(view1.__call_permissive__, im_func) + is getattr(view2.__call_permissive__, im_func) + ) + self.assertTrue( + getattr(view1.__permitted__, im_func) + is getattr(view2.__permitted__, im_func) + ) + self.assertTrue( + getattr(view1.__predicated__, im_func) + is getattr(view2.__predicated__, im_func) + ) class TestStaticURLInfo(unittest.TestCase): def _getTargetClass(self): from pyramid.config.views import StaticURLInfo + return StaticURLInfo def _makeOne(self): @@ -3124,11 +3780,13 @@ class TestStaticURLInfo(unittest.TestCase): def test_verifyClass(self): from pyramid.interfaces import IStaticURLInfo from zope.interface.verify import verifyClass + verifyClass(IStaticURLInfo, self._getTargetClass()) def test_verifyObject(self): from pyramid.interfaces import IStaticURLInfo from zope.interface.verify import verifyObject + verifyObject(IStaticURLInfo, self._makeOne()) def test_generate_missing(self): @@ -3140,27 +3798,33 @@ class TestStaticURLInfo(unittest.TestCase): inst = self._makeOne() inst.registrations = [ (None, 'spec', 'route_name'), - ('http://example.com/foo/', 'package:path/', None)] + ('http://example.com/foo/', 'package:path/', None), + ] request = self._makeRequest() result = inst.generate('package:path/abc', request) self.assertEqual(result, 'http://example.com/foo/abc') def test_generate_slash_in_name1(self): inst = self._makeOne() - inst.registrations = [('http://example.com/foo/', 'package:path/', None)] + inst.registrations = [ + ('http://example.com/foo/', 'package:path/', None) + ] request = self._makeRequest() result = inst.generate('package:path/abc', request) self.assertEqual(result, 'http://example.com/foo/abc') def test_generate_slash_in_name2(self): inst = self._makeOne() - inst.registrations = [('http://example.com/foo/', 'package:path/', None)] + inst.registrations = [ + ('http://example.com/foo/', 'package:path/', None) + ] request = self._makeRequest() result = inst.generate('package:path/', request) self.assertEqual(result, 'http://example.com/foo/') def test_generate_quoting(self): from pyramid.interfaces import IStaticURLInfo + config = testing.setUp() try: config.add_static_view('images', path='mypkg:templates') @@ -3175,10 +3839,12 @@ class TestStaticURLInfo(unittest.TestCase): def test_generate_route_url(self): inst = self._makeOne() inst.registrations = [(None, 'package:path/', '__viewname/')] + def route_url(n, **kw): self.assertEqual(n, '__viewname/') - self.assertEqual(kw, {'subpath':'abc', 'a':1}) + self.assertEqual(kw, {'subpath': 'abc', 'a': 1}) return 'url' + request = self._makeRequest() request.route_url = route_url result = inst.generate('package:path/abc', request, a=1) @@ -3187,10 +3853,12 @@ class TestStaticURLInfo(unittest.TestCase): def test_generate_url_unquoted_local(self): inst = self._makeOne() inst.registrations = [(None, 'package:path/', '__viewname/')] + def route_url(n, **kw): self.assertEqual(n, '__viewname/') - self.assertEqual(kw, {'subpath':'abc def', 'a':1}) + self.assertEqual(kw, {'subpath': 'abc def', 'a': 1}) return 'url' + request = self._makeRequest() request.route_url = route_url result = inst.generate('package:path/abc def', request, a=1) @@ -3208,72 +3876,101 @@ class TestStaticURLInfo(unittest.TestCase): registrations = [('http://example.com/', 'package:path/', None)] inst.registrations = registrations request = self._makeRequest() - result = inst.generate('package:path/abc def', request, a=1, - _query='(openlayers)') - self.assertEqual(result, - 'http://example.com/abc%20def?(openlayers)') + result = inst.generate( + 'package:path/abc def', request, a=1, _query='(openlayers)' + ) + self.assertEqual(result, 'http://example.com/abc%20def?(openlayers)') def test_generate_url_with_custom_anchor(self): inst = self._makeOne() inst.registrations = [('http://example.com/', 'package:path/', None)] request = self._makeRequest() uc = text_(b'La Pe\xc3\xb1a', 'utf-8') - result = inst.generate('package:path/abc def', request, a=1, _anchor=uc) - self.assertEqual(result, - 'http://example.com/abc%20def#La%20Pe%C3%B1a') + result = inst.generate( + 'package:path/abc def', request, a=1, _anchor=uc + ) + self.assertEqual(result, 'http://example.com/abc%20def#La%20Pe%C3%B1a') def test_generate_url_cachebust(self): def cachebust(request, subpath, kw): kw['foo'] = 'bar' return 'foo' + '/' + subpath, kw + inst = self._makeOne() inst.registrations = [(None, 'package:path/', '__viewname')] inst.cache_busters = [('package:path/', cachebust, False)] request = self._makeRequest() called = [False] + def route_url(n, **kw): called[0] = True self.assertEqual(n, '__viewname') - self.assertEqual(kw, {'subpath': 'foo/abc', 'foo': 'bar', - 'pathspec': 'package:path/abc', - 'rawspec': 'package:path/abc'}) + self.assertEqual( + kw, + { + 'subpath': 'foo/abc', + 'foo': 'bar', + 'pathspec': 'package:path/abc', + 'rawspec': 'package:path/abc', + }, + ) + request.route_url = route_url inst.generate('package:path/abc', request) self.assertTrue(called[0]) def test_generate_url_cachebust_abspath(self): here = os.path.dirname(__file__) + os.sep + def cachebust(pathspec, subpath, kw): kw['foo'] = 'bar' return 'foo' + '/' + subpath, kw + inst = self._makeOne() inst.registrations = [(None, here, '__viewname')] inst.cache_busters = [(here, cachebust, False)] request = self._makeRequest() called = [False] + def route_url(n, **kw): called[0] = True self.assertEqual(n, '__viewname') - self.assertEqual(kw, {'subpath': 'foo/abc', 'foo': 'bar', - 'pathspec': here + 'abc', - 'rawspec': here + 'abc'}) + self.assertEqual( + kw, + { + 'subpath': 'foo/abc', + 'foo': 'bar', + 'pathspec': here + 'abc', + 'rawspec': here + 'abc', + }, + ) + request.route_url = route_url inst.generate(here + 'abc', request) self.assertTrue(called[0]) def test_generate_url_cachebust_nomatch(self): - def fake_cb(*a, **kw): raise AssertionError + def fake_cb(*a, **kw): + raise AssertionError + inst = self._makeOne() inst.registrations = [(None, 'package:path/', '__viewname')] inst.cache_busters = [('package:path2/', fake_cb, False)] request = self._makeRequest() called = [False] + def route_url(n, **kw): called[0] = True self.assertEqual(n, '__viewname') - self.assertEqual(kw, {'subpath': 'abc', - 'pathspec': 'package:path/abc', - 'rawspec': 'package:path/abc'}) + self.assertEqual( + kw, + { + 'subpath': 'abc', + 'pathspec': 'package:path/abc', + 'rawspec': 'package:path/abc', + }, + ) + request.route_url = route_url inst.generate('package:path/abc', request) self.assertTrue(called[0]) @@ -3284,13 +3981,16 @@ class TestStaticURLInfo(unittest.TestCase): request = testing.DummyRequest() config.add_static_view('static', 'path') config.override_asset( - 'tests.test_config:path/', - 'tests.test_config:other_path/') + 'tests.test_config:path/', 'tests.test_config:other_path/' + ) + def cb(val): def cb_(request, subpath, kw): kw['_query'] = {'x': val} return subpath, kw + return cb_ + config.add_cache_buster('path', cb('foo')) result = request.static_url('path/foo.png') self.assertEqual(result, 'http://example.com/static/foo.png?x=foo') @@ -3339,6 +4039,7 @@ class TestStaticURLInfo(unittest.TestCase): def test_add_viewname(self): from pyramid.security import NO_PERMISSION_REQUIRED from pyramid.static import static_view + config = DummyConfig() inst = self._makeOne() inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1) @@ -3352,7 +4053,7 @@ class TestStaticURLInfo(unittest.TestCase): config = DummyConfig() config.route_prefix = '/abc' inst = self._makeOne() - inst.add(config, 'view', 'anotherpackage:path',) + inst.add(config, 'view', 'anotherpackage:path') expected = [(None, 'anotherpackage:path/', '__/abc/view/')] self.assertEqual(inst.registrations, expected) self.assertEqual(config.route_args, ('__/abc/view/', 'view/*subpath')) @@ -3360,31 +4061,52 @@ class TestStaticURLInfo(unittest.TestCase): def test_add_viewname_with_permission(self): config = DummyConfig() inst = self._makeOne() - inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, - permission='abc') + inst.add( + config, + 'view', + 'anotherpackage:path', + cache_max_age=1, + permission='abc', + ) self.assertEqual(config.view_kw['permission'], 'abc') def test_add_viewname_with_context(self): config = DummyConfig() inst = self._makeOne() - inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, - context=DummyContext) + inst.add( + config, + 'view', + 'anotherpackage:path', + cache_max_age=1, + context=DummyContext, + ) self.assertEqual(config.view_kw['context'], DummyContext) def test_add_viewname_with_for_(self): config = DummyConfig() inst = self._makeOne() - inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, - for_=DummyContext) + inst.add( + config, + 'view', + 'anotherpackage:path', + cache_max_age=1, + for_=DummyContext, + ) self.assertEqual(config.view_kw['context'], DummyContext) def test_add_viewname_with_renderer(self): config = DummyConfig() inst = self._makeOne() - inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, - renderer='mypackage:templates/index.pt') - self.assertEqual(config.view_kw['renderer'], - 'mypackage:templates/index.pt') + inst.add( + config, + 'view', + 'anotherpackage:path', + cache_max_age=1, + renderer='mypackage:templates/index.pt', + ) + self.assertEqual( + config.view_kw['renderer'], 'mypackage:templates/index.pt' + ) def test_add_cachebust_prevented(self): config = DummyConfig() @@ -3397,7 +4119,9 @@ class TestStaticURLInfo(unittest.TestCase): def test_add_cachebuster(self): config = DummyConfig() inst = self._makeOne() - inst.add_cache_buster(config, 'mypackage:path', DummyCacheBuster('foo')) + inst.add_cache_buster( + config, 'mypackage:path', DummyCacheBuster('foo') + ) cachebust = inst.cache_busters[-1][1] subpath, kw = cachebust(None, 'some/path', {}) self.assertEqual(subpath, 'some/path') @@ -3418,8 +4142,7 @@ class TestStaticURLInfo(unittest.TestCase): cb2 = DummyCacheBuster('bar') inst.add_cache_buster(config, 'mypackage:path/', cb1) inst.add_cache_buster(config, 'mypackage:path', cb2) - self.assertEqual(inst.cache_busters, - [('mypackage:path/', cb2, False)]) + self.assertEqual(inst.cache_busters, [('mypackage:path/', cb2, False)]) def test_add_cachebuster_overwrite_explicit(self): config = DummyConfig() @@ -3428,9 +4151,10 @@ class TestStaticURLInfo(unittest.TestCase): cb2 = DummyCacheBuster('bar') inst.add_cache_buster(config, 'mypackage:path/', cb1) inst.add_cache_buster(config, 'mypackage:path', cb2, True) - self.assertEqual(inst.cache_busters, - [('mypackage:path/', cb1, False), - ('mypackage:path/', cb2, True)]) + self.assertEqual( + inst.cache_busters, + [('mypackage:path/', cb1, False), ('mypackage:path/', cb2, True)], + ) def test_add_cachebuster_for_more_specific_path(self): config = DummyConfig() @@ -3447,36 +4171,47 @@ class TestStaticURLInfo(unittest.TestCase): inst.add_cache_buster(config, 'mypackage:path/sub/less', cb5, True) self.assertEqual( inst.cache_busters, - [('mypackage:path/', cb1, False), - ('mypackage:path/sub/other/', cb3, False), - ('mypackage:path/sub/', cb2, True), - ('mypackage:path/sub/less/', cb5, True), - ('mypackage:path/sub/other/', cb4, True)]) + [ + ('mypackage:path/', cb1, False), + ('mypackage:path/sub/other/', cb3, False), + ('mypackage:path/sub/', cb2, True), + ('mypackage:path/sub/less/', cb5, True), + ('mypackage:path/sub/other/', cb4, True), + ], + ) + class Test_view_description(unittest.TestCase): def _callFUT(self, view): from pyramid.config.views import view_description + return view_description(view) def test_with_text(self): - def view(): pass + def view(): + pass + view.__text__ = 'some text' result = self._callFUT(view) self.assertEqual(result, 'some text') def test_without_text(self): - def view(): pass + def view(): + pass + result = self._callFUT(view) - self.assertEqual(result, - 'function tests.test_config.test_views.view') + self.assertEqual(result, 'function tests.test_config.test_views.view') + class Test_viewdefaults(unittest.TestCase): def _makeOne(self, wrapped): from pyramid.decorator import reify + return reify(wrapped) def test_dunder_attrs_copied(self): from pyramid.config.views import viewdefaults + decorator = self._makeOne(viewdefaults) self.assertEqual(decorator.__doc__, viewdefaults.__doc__) self.assertEqual(decorator.__name__, viewdefaults.__name__) @@ -3492,11 +4227,10 @@ class DummyRegistry: def queryUtility(self, type_or_iface, name=None, default=None): return self.utility or default + from zope.interface import implementer -from pyramid.interfaces import ( - IResponse, - IRequest, - ) +from pyramid.interfaces import IResponse, IRequest + @implementer(IResponse) class DummyResponse(object): @@ -3504,10 +4238,11 @@ class DummyResponse(object): default_content_type = None body = None + class DummyRequest: subpath = () matchdict = None - request_iface = IRequest + request_iface = IRequest application_url = 'http://example.com/foo' def __init__(self, environ=None): @@ -3518,9 +4253,11 @@ class DummyRequest: self.cookies = {} self.response = DummyResponse() + class DummyContext: pass + class DummyAccept(object): def __init__(self, *matches, **kw): self.matches = list(matches) @@ -3536,11 +4273,13 @@ class DummyAccept(object): def __contains__(self, value): return self.contains + class DummyConfig: def __init__(self): self.registry = DummyRegistry() route_prefix = '' + def add_route(self, *args, **kw): self.route_args = args self.route_kw = kw @@ -3555,20 +4294,27 @@ class DummyConfig: def introspectable(self, *arg): return {} + from zope.interface import implementer from pyramid.interfaces import IMultiView + + @implementer(IMultiView) class DummyMultiView: def __init__(self): self.views = [] self.name = 'name' + def add(self, view, order, phash=None, accept=None, accept_order=None): self.views.append((view, phash, accept, accept_order)) + def __call__(self, context, request): return 'OK1' + def __permitted__(self, context, request): """ """ + class DummyCacheBuster(object): def __init__(self, token): self.token = token @@ -3577,19 +4323,23 @@ class DummyCacheBuster(object): kw['x'] = self.token return subpath, kw + def parse_httpdate(s): import datetime + # cannot use %Z, must use literal GMT; Jython honors timezone # but CPython does not return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT") + def assert_similar_datetime(one, two): for attr in ('year', 'month', 'day', 'hour', 'minute'): one_attr = getattr(one, attr) two_attr = getattr(two, attr) - if not one_attr == two_attr: # pragma: no cover + if not one_attr == two_attr: # pragma: no cover raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr)) + class DummyStaticURLInfo: def __init__(self): self.added = [] @@ -3597,15 +4347,17 @@ class DummyStaticURLInfo: def add(self, config, name, spec, **kw): self.added.append((config, name, spec, kw)) + class DummyViewDefaultsClass(object): - __view_defaults__ = { - 'containment':'tests.test_config.IDummy' - } + __view_defaults__ = {'containment': 'tests.test_config.IDummy'} + def __init__(self, request): pass + def __call__(self): return 'OK' + class DummyPredicate(object): def __init__(self, val, config): self.val = val @@ -3615,18 +4367,23 @@ class DummyPredicate(object): phash = text + class DummyIntrospector(object): def __init__(self, getval=None): self.related = [] self.introspectables = [] self.getval = getval + def add(self, introspectable): self.introspectables.append(introspectable) + def get(self, name, discrim): return self.getval + def relate(self, a, b): self.related.append((a, b)) + class DummySession(dict): def get_csrf_token(self): return self['csrf_token'] diff --git a/tests/test_csrf.py b/tests/test_csrf.py index a224d928f..d1b569c32 100644 --- a/tests/test_csrf.py +++ b/tests/test_csrf.py @@ -18,6 +18,7 @@ class TestLegacySessionCSRFStoragePolicy(unittest.TestCase): def _makeOne(self): from pyramid.csrf import LegacySessionCSRFStoragePolicy + return LegacySessionCSRFStoragePolicy() def test_register_session_csrf_policy(self): @@ -37,12 +38,10 @@ class TestLegacySessionCSRFStoragePolicy(unittest.TestCase): request = DummyRequest(session=self.MockSession()) self.assertEqual( - policy.get_csrf_token(request), - '02821185e4c94269bdc38e6eeae0a2f8' + policy.get_csrf_token(request), '02821185e4c94269bdc38e6eeae0a2f8' ) self.assertEqual( - policy.new_csrf_token(request), - 'e5e9e30a08b34ff9842ff7d2b958c14b' + policy.new_csrf_token(request), 'e5e9e30a08b34ff9842ff7d2b958c14b' ) def test_check_csrf_token(self): @@ -56,6 +55,7 @@ class TestLegacySessionCSRFStoragePolicy(unittest.TestCase): class TestSessionCSRFStoragePolicy(unittest.TestCase): def _makeOne(self, **kw): from pyramid.csrf import SessionCSRFStoragePolicy + return SessionCSRFStoragePolicy(**kw) def test_register_session_csrf_policy(self): @@ -101,6 +101,7 @@ class TestSessionCSRFStoragePolicy(unittest.TestCase): class TestCookieCSRFStoragePolicy(unittest.TestCase): def _makeOne(self, **kw): from pyramid.csrf import CookieCSRFStoragePolicy + return CookieCSRFStoragePolicy(**kw) def test_register_cookie_csrf_policy(self): @@ -124,8 +125,12 @@ class TestCookieCSRFStoragePolicy(unittest.TestCase): request.response_callback(request, response) self.assertEqual( response.headerlist, - [('Set-Cookie', 'csrf_token={}; Path=/; SameSite=Lax'.format( - token))] + [ + ( + 'Set-Cookie', + 'csrf_token={}; Path=/; SameSite=Lax'.format(token), + ) + ], ) def test_get_cookie_csrf_nondefault_samesite(self): @@ -137,7 +142,7 @@ class TestCookieCSRFStoragePolicy(unittest.TestCase): request.response_callback(request, response) self.assertEqual( response.headerlist, - [('Set-Cookie', 'csrf_token={}; Path=/'.format(token))] + [('Set-Cookie', 'csrf_token={}; Path=/'.format(token))], ) def test_existing_cookie_csrf_does_not_set_cookie(self): @@ -147,10 +152,7 @@ class TestCookieCSRFStoragePolicy(unittest.TestCase): policy = self._makeOne() token = policy.get_csrf_token(request) - self.assertEqual( - token, - 'e6f325fee5974f3da4315a8ccf4513d2' - ) + self.assertEqual(token, 'e6f325fee5974f3da4315a8ccf4513d2') self.assertIsNone(request.response_callback) def test_new_cookie_csrf_with_existing_cookie_sets_cookies(self): @@ -164,8 +166,12 @@ class TestCookieCSRFStoragePolicy(unittest.TestCase): request.response_callback(request, response) self.assertEqual( response.headerlist, - [('Set-Cookie', 'csrf_token={}; Path=/; SameSite=Lax'.format(token) - )] + [ + ( + 'Set-Cookie', + 'csrf_token={}; Path=/; SameSite=Lax'.format(token), + ) + ], ) def test_get_csrf_token_returns_the_new_token(self): @@ -189,12 +195,14 @@ class TestCookieCSRFStoragePolicy(unittest.TestCase): self.assertTrue(policy.check_csrf_token(request, 'foo')) self.assertFalse(policy.check_csrf_token(request, 'bar')) + class Test_get_csrf_token(unittest.TestCase): def setUp(self): self.config = testing.setUp() def _callFUT(self, *args, **kwargs): from pyramid.csrf import get_csrf_token + return get_csrf_token(*args, **kwargs) def test_no_override_csrf_utility_registered(self): @@ -216,6 +224,7 @@ class Test_new_csrf_token(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid.csrf import new_csrf_token + return new_csrf_token(*args, **kwargs) def test_no_override_csrf_utility_registered(self): @@ -240,6 +249,7 @@ class Test_check_csrf_token(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid.csrf import check_csrf_token + return check_csrf_token(*args, **kwargs) def test_success_token(self): @@ -266,9 +276,9 @@ class Test_check_csrf_token(unittest.TestCase): def test_failure_raises(self): from pyramid.exceptions import BadCSRFToken + request = testing.DummyRequest() - self.assertRaises(BadCSRFToken, self._callFUT, request, - 'csrf_token') + self.assertRaises(BadCSRFToken, self._callFUT, request, 'csrf_token') def test_failure_no_raises(self): request = testing.DummyRequest() @@ -282,6 +292,7 @@ class Test_check_csrf_token_without_defaults_configured(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid.csrf import check_csrf_token + return check_csrf_token(*args, **kwargs) def test_success_token(self): @@ -292,9 +303,9 @@ class Test_check_csrf_token_without_defaults_configured(unittest.TestCase): def test_failure_raises(self): from pyramid.exceptions import BadCSRFToken + request = testing.DummyRequest() - self.assertRaises(BadCSRFToken, self._callFUT, request, - 'csrf_token') + self.assertRaises(BadCSRFToken, self._callFUT, request, 'csrf_token') def test_failure_no_raises(self): request = testing.DummyRequest() @@ -305,6 +316,7 @@ class Test_check_csrf_token_without_defaults_configured(unittest.TestCase): class Test_check_csrf_origin(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid.csrf import check_csrf_origin + return check_csrf_origin(*args, **kwargs) def test_success_with_http(self): @@ -338,7 +350,7 @@ class Test_check_csrf_origin(unittest.TestCase): request.host_port = "443" request.referrer = "https://not-example.com/login/" request.registry.settings = { - "pyramid.csrf_trusted_origins": ["not-example.com"], + "pyramid.csrf_trusted_origins": ["not-example.com"] } self.assertTrue(self._callFUT(request)) @@ -353,6 +365,7 @@ class Test_check_csrf_origin(unittest.TestCase): def test_fails_with_wrong_host(self): from pyramid.exceptions import BadCSRFOrigin + request = testing.DummyRequest() request.scheme = "https" request.host = "example.com" @@ -364,6 +377,7 @@ class Test_check_csrf_origin(unittest.TestCase): def test_fails_with_no_origin(self): from pyramid.exceptions import BadCSRFOrigin + request = testing.DummyRequest() request.scheme = "https" request.referrer = None @@ -372,6 +386,7 @@ class Test_check_csrf_origin(unittest.TestCase): def test_fails_when_http_to_https(self): from pyramid.exceptions import BadCSRFOrigin + request = testing.DummyRequest() request.scheme = "https" request.host = "example.com" @@ -383,6 +398,7 @@ class Test_check_csrf_origin(unittest.TestCase): def test_fails_with_nonstandard_port(self): from pyramid.exceptions import BadCSRFOrigin + request = testing.DummyRequest() request.scheme = "https" request.host = "example.com:8080" diff --git a/tests/test_decorator.py b/tests/test_decorator.py index 4b9313e06..2dcc9b4d3 100644 --- a/tests/test_decorator.py +++ b/tests/test_decorator.py @@ -1,13 +1,16 @@ import unittest + class TestReify(unittest.TestCase): def _makeOne(self, wrapped): from pyramid.decorator import reify + return reify(wrapped) def test___get__withinst(self): def wrapped(inst): return 'a' + decorator = self._makeOne(wrapped) inst = Dummy() result = decorator.__get__(inst) @@ -17,6 +20,7 @@ class TestReify(unittest.TestCase): def test___get__noinst(self): def wrapped(inst): return 'a' # pragma: no cover + decorator = self._makeOne(wrapped) result = decorator.__get__(None) self.assertEqual(result, decorator) diff --git a/tests/test_docs.py b/tests/test_docs.py index 0735a494a..46c9ed765 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -15,6 +15,7 @@ if 0: import manuel.codeblock import manuel.capture import manuel.ignore + m = manuel.ignore.Manuel() m += manuel.codeblock.Manuel() m += manuel.capture.Manuel() diff --git a/tests/test_encode.py b/tests/test_encode.py index d3a9f7095..f70050cac 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -1,31 +1,30 @@ import unittest -from pyramid.compat import ( - text_, - native_, - ) +from pyramid.compat import text_, native_ + class UrlEncodeTests(unittest.TestCase): def _callFUT(self, query, doseq=False, **kw): from pyramid.encode import urlencode + return urlencode(query, doseq, **kw) def test_ascii_only(self): - result = self._callFUT([('a',1), ('b',2)]) + result = self._callFUT([('a', 1), ('b', 2)]) self.assertEqual(result, 'a=1&b=2') def test_unicode_key(self): la = text_(b'LaPe\xc3\xb1a', 'utf-8') - result = self._callFUT([(la, 1), ('b',2)]) + result = self._callFUT([(la, 1), ('b', 2)]) self.assertEqual(result, 'LaPe%C3%B1a=1&b=2') def test_unicode_val_single(self): la = text_(b'LaPe\xc3\xb1a', 'utf-8') - result = self._callFUT([('a', la), ('b',2)]) + result = self._callFUT([('a', la), ('b', 2)]) self.assertEqual(result, 'a=LaPe%C3%B1a&b=2') def test_unicode_val_multiple(self): la = [text_(b'LaPe\xc3\xb1a', 'utf-8')] * 2 - result = self._callFUT([('a', la), ('b',2)], doseq=True) + result = self._callFUT([('a', la), ('b', 2)], doseq=True) self.assertEqual(result, 'a=LaPe%C3%B1a&a=LaPe%C3%B1a&b=2') def test_int_val_multiple(self): @@ -38,7 +37,7 @@ class UrlEncodeTests(unittest.TestCase): self.assertEqual(result, 'a=123+456') def test_dict(self): - result = self._callFUT({'a':1}) + result = self._callFUT({'a': 1}) self.assertEqual(result, 'a=1') def test_None_value(self): @@ -56,20 +55,24 @@ class UrlEncodeTests(unittest.TestCase): def test_quote_via(self): def my_quoter(value): return 'xxx' + value - result = self._callFUT([('a', '1'), ('b', None), ('c', None)], - quote_via=my_quoter) + + result = self._callFUT( + [('a', '1'), ('b', None), ('c', None)], quote_via=my_quoter + ) self.assertEqual(result, 'xxxa=xxx1&xxxb=&xxxc=') + class URLQuoteTests(unittest.TestCase): def _callFUT(self, val, safe=''): from pyramid.encode import url_quote + return url_quote(val, safe) def test_it_bytes(self): la = b'La/Pe\xc3\xb1a' result = self._callFUT(la) self.assertEqual(result, 'La%2FPe%C3%B1a') - + def test_it_native(self): la = native_(b'La/Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) diff --git a/tests/test_events.py b/tests/test_events.py index 793ac329f..a08cab637 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -1,9 +1,11 @@ import unittest from pyramid import testing + class NewRequestEventTests(unittest.TestCase): def _getTargetClass(self): from pyramid.events import NewRequest + return NewRequest def _makeOne(self, request): @@ -12,12 +14,14 @@ class NewRequestEventTests(unittest.TestCase): def test_class_conforms_to_INewRequest(self): from pyramid.interfaces import INewRequest from zope.interface.verify import verifyClass + klass = self._getTargetClass() verifyClass(INewRequest, klass) def test_instance_conforms_to_INewRequest(self): from pyramid.interfaces import INewRequest from zope.interface.verify import verifyObject + request = DummyRequest() inst = self._makeOne(request) verifyObject(INewRequest, inst) @@ -27,9 +31,11 @@ class NewRequestEventTests(unittest.TestCase): inst = self._makeOne(request) self.assertEqual(inst.request, request) + class NewResponseEventTests(unittest.TestCase): def _getTargetClass(self): from pyramid.events import NewResponse + return NewResponse def _makeOne(self, request, response): @@ -38,12 +44,14 @@ class NewResponseEventTests(unittest.TestCase): def test_class_conforms_to_INewResponse(self): from pyramid.interfaces import INewResponse from zope.interface.verify import verifyClass + klass = self._getTargetClass() verifyClass(INewResponse, klass) def test_instance_conforms_to_INewResponse(self): from pyramid.interfaces import INewResponse from zope.interface.verify import verifyObject + request = DummyRequest() response = DummyResponse() inst = self._makeOne(request, response) @@ -56,9 +64,11 @@ class NewResponseEventTests(unittest.TestCase): self.assertEqual(inst.request, request) self.assertEqual(inst.response, response) + class ApplicationCreatedEventTests(unittest.TestCase): def _getTargetClass(self): from pyramid.events import ApplicationCreated + return ApplicationCreated def _makeOne(self, context=object()): @@ -67,31 +77,39 @@ class ApplicationCreatedEventTests(unittest.TestCase): def test_class_conforms_to_IApplicationCreated(self): from pyramid.interfaces import IApplicationCreated from zope.interface.verify import verifyClass + verifyClass(IApplicationCreated, self._getTargetClass()) def test_object_conforms_to_IApplicationCreated(self): from pyramid.interfaces import IApplicationCreated from zope.interface.verify import verifyObject + verifyObject(IApplicationCreated, self._makeOne()) + class WSGIApplicationCreatedEventTests(ApplicationCreatedEventTests): def _getTargetClass(self): from pyramid.events import WSGIApplicationCreatedEvent + return WSGIApplicationCreatedEvent def test_class_conforms_to_IWSGIApplicationCreatedEvent(self): from pyramid.interfaces import IWSGIApplicationCreatedEvent from zope.interface.verify import verifyClass + verifyClass(IWSGIApplicationCreatedEvent, self._getTargetClass()) def test_object_conforms_to_IWSGIApplicationCreatedEvent(self): from pyramid.interfaces import IWSGIApplicationCreatedEvent from zope.interface.verify import verifyObject + verifyObject(IWSGIApplicationCreatedEvent, self._makeOne()) + class ContextFoundEventTests(unittest.TestCase): def _getTargetClass(self): from pyramid.events import ContextFound + return ContextFound def _makeOne(self, request=None): @@ -102,31 +120,39 @@ class ContextFoundEventTests(unittest.TestCase): def test_class_conforms_to_IContextFound(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IContextFound + verifyClass(IContextFound, self._getTargetClass()) def test_instance_conforms_to_IContextFound(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IContextFound + verifyObject(IContextFound, self._makeOne()) + class AfterTraversalEventTests(ContextFoundEventTests): def _getTargetClass(self): from pyramid.events import AfterTraversal + return AfterTraversal def test_class_conforms_to_IAfterTraversal(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IAfterTraversal + verifyClass(IAfterTraversal, self._getTargetClass()) def test_instance_conforms_to_IAfterTraversal(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IAfterTraversal + verifyObject(IAfterTraversal, self._makeOne()) + class BeforeTraversalEventTests(unittest.TestCase): def _getTargetClass(self): from pyramid.events import BeforeTraversal + return BeforeTraversal def _makeOne(self, request=None): @@ -137,11 +163,13 @@ class BeforeTraversalEventTests(unittest.TestCase): def test_class_conforms_to_IBeforeTraversal(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IBeforeTraversal + verifyClass(IBeforeTraversal, self._getTargetClass()) def test_instance_conforms_to_IBeforeTraversal(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IBeforeTraversal + verifyObject(IBeforeTraversal, self._makeOne()) @@ -154,14 +182,23 @@ class TestSubscriber(unittest.TestCase): def _makeOne(self, *ifaces, **predicates): from pyramid.events import subscriber + return subscriber(*ifaces, **predicates) def test_register_single(self): from zope.interface import Interface - class IFoo(Interface): pass - class IBar(Interface): pass + + class IFoo(Interface): + pass + + class IBar(Interface): + pass + dec = self._makeOne(IFoo) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -170,10 +207,18 @@ class TestSubscriber(unittest.TestCase): def test_register_multi(self): from zope.interface import Interface - class IFoo(Interface): pass - class IBar(Interface): pass + + class IFoo(Interface): + pass + + class IBar(Interface): + pass + dec = self._makeOne(IFoo, IBar) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -182,8 +227,12 @@ class TestSubscriber(unittest.TestCase): def test_register_none_means_all(self): from zope.interface import Interface + dec = self._makeOne() - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -192,10 +241,18 @@ class TestSubscriber(unittest.TestCase): def test_register_objectevent(self): from zope.interface import Interface - class IFoo(Interface): pass - class IBar(Interface): pass + + class IFoo(Interface): + pass + + class IBar(Interface): + pass + dec = self._makeOne([IFoo, IBar]) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -206,67 +263,84 @@ class TestSubscriber(unittest.TestCase): dec = self._makeOne() dummy_venusian = DummyVenusian() dec.venusian = dummy_venusian - def foo(): pass + + def foo(): + pass + dec(foo) - self.assertEqual(dummy_venusian.attached, - [(foo, dec.register, 'pyramid', 1)]) + self.assertEqual( + dummy_venusian.attached, [(foo, dec.register, 'pyramid', 1)] + ) def test___call___with_venusian_args(self): dec = self._makeOne(_category='foo', _depth=1) dummy_venusian = DummyVenusian() dec.venusian = dummy_venusian - def foo(): pass + + def foo(): + pass + dec(foo) - self.assertEqual(dummy_venusian.attached, - [(foo, dec.register, 'foo', 2)]) + self.assertEqual( + dummy_venusian.attached, [(foo, dec.register, 'foo', 2)] + ) def test_regsister_with_predicates(self): from zope.interface import Interface + dec = self._makeOne(a=1) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config dec.register(scanner, None, foo) - self.assertEqual(config.subscribed, [(foo, Interface, {'a':1})]) + self.assertEqual(config.subscribed, [(foo, Interface, {'a': 1})]) + class TestBeforeRender(unittest.TestCase): def _makeOne(self, system, val=None): from pyramid.events import BeforeRender + return BeforeRender(system, val) - @testing.skip_on('pypy') # see https://github.com/Pylons/pyramid/issues/3237 + @testing.skip_on( + 'pypy' + ) # see https://github.com/Pylons/pyramid/issues/3237 def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IBeforeRender + event = self._makeOne({}) verifyObject(IBeforeRender, event) def test_setitem_success(self): event = self._makeOne({}) event['a'] = 1 - self.assertEqual(event, {'a':1}) + self.assertEqual(event, {'a': 1}) def test_setdefault_fail(self): event = self._makeOne({}) result = event.setdefault('a', 1) self.assertEqual(result, 1) - self.assertEqual(event, {'a':1}) + self.assertEqual(event, {'a': 1}) def test_setdefault_success(self): event = self._makeOne({}) event['a'] = 1 result = event.setdefault('a', 2) self.assertEqual(result, 1) - self.assertEqual(event, {'a':1}) + self.assertEqual(event, {'a': 1}) def test_update_success(self): - event = self._makeOne({'a':1}) - event.update({'b':2}) - self.assertEqual(event, {'a':1, 'b':2}) + event = self._makeOne({'a': 1}) + event.update({'b': 2}) + self.assertEqual(event, {'a': 1, 'b': 2}) def test__contains__True(self): - system = {'a':1} + system = {'a': 1} event = self._makeOne(system) self.assertTrue('a' in event) @@ -276,7 +350,7 @@ class TestBeforeRender(unittest.TestCase): self.assertFalse('a' in event) def test__getitem__success(self): - system = {'a':1} + system = {'a': 1} event = self._makeOne(system) self.assertEqual(event['a'], 1) @@ -286,7 +360,7 @@ class TestBeforeRender(unittest.TestCase): self.assertRaises(KeyError, event.__getitem__, 'a') def test_get_success(self): - system = {'a':1} + system = {'a': 1} event = self._makeOne(system) self.assertEqual(event.get('a'), 1) @@ -301,6 +375,7 @@ class TestBeforeRender(unittest.TestCase): event = self._makeOne(system, val) self.assertTrue(event.rendering_val is val) + class DummyConfigurator(object): def __init__(self): self.subscribed = [] @@ -311,9 +386,11 @@ class DummyConfigurator(object): else: self.subscribed.append((wrapped, ifaces, predicates)) + class DummyRegistry(object): pass + class DummyVenusian(object): def __init__(self): self.attached = [] @@ -321,12 +398,14 @@ class DummyVenusian(object): def attach(self, wrapped, fn, category=None, depth=None): self.attached.append((wrapped, fn, category, depth)) + class Dummy: pass + class DummyRequest: pass + class DummyResponse: pass - diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 9cb0f58d1..399940c05 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,29 +1,37 @@ import unittest + class TestBWCompat(unittest.TestCase): def test_bwcompat_notfound(self): from pyramid.exceptions import NotFound as one from pyramid.httpexceptions import HTTPNotFound as two + self.assertTrue(one is two) def test_bwcompat_forbidden(self): from pyramid.exceptions import Forbidden as one from pyramid.httpexceptions import HTTPForbidden as two + self.assertTrue(one is two) + class TestBadCSRFToken(unittest.TestCase): def test_response_equivalence(self): from pyramid.exceptions import BadCSRFToken from pyramid.httpexceptions import HTTPBadRequest + self.assertTrue(isinstance(BadCSRFToken(), HTTPBadRequest)) + class TestNotFound(unittest.TestCase): def _makeOne(self, message): from pyramid.exceptions import NotFound + return NotFound(message) def test_it(self): from pyramid.interfaces import IExceptionResponse + e = self._makeOne('notfound') self.assertTrue(IExceptionResponse.providedBy(e)) self.assertEqual(e.status, '404 Not Found') @@ -32,15 +40,19 @@ class TestNotFound(unittest.TestCase): def test_response_equivalence(self): from pyramid.exceptions import NotFound from pyramid.httpexceptions import HTTPNotFound + self.assertTrue(NotFound is HTTPNotFound) + class TestForbidden(unittest.TestCase): def _makeOne(self, message): from pyramid.exceptions import Forbidden + return Forbidden(message) def test_it(self): from pyramid.interfaces import IExceptionResponse + e = self._makeOne('forbidden') self.assertTrue(IExceptionResponse.providedBy(e)) self.assertEqual(e.status, '403 Forbidden') @@ -49,18 +61,22 @@ class TestForbidden(unittest.TestCase): def test_response_equivalence(self): from pyramid.exceptions import Forbidden from pyramid.httpexceptions import HTTPForbidden + self.assertTrue(Forbidden is HTTPForbidden) + class TestConfigurationConflictError(unittest.TestCase): def _makeOne(self, conflicts): from pyramid.exceptions import ConfigurationConflictError + return ConfigurationConflictError(conflicts) def test_str(self): - conflicts = {'a':('1', '2', '3'), 'b':('4', '5', '6')} + conflicts = {'a': ('1', '2', '3'), 'b': ('4', '5', '6')} exc = self._makeOne(conflicts) - self.assertEqual(str(exc), -"""\ + self.assertEqual( + str(exc), + """\ Conflicting configuration actions For: a 1 @@ -69,24 +85,29 @@ Conflicting configuration actions For: b 4 5 - 6""") + 6""", + ) + class TestConfigurationExecutionError(unittest.TestCase): def _makeOne(self, etype, evalue, info): from pyramid.exceptions import ConfigurationExecutionError + return ConfigurationExecutionError(etype, evalue, info) def test_str(self): exc = self._makeOne('etype', 'evalue', 'info') self.assertEqual(str(exc), 'etype: evalue\n in:\n info') - + + class TestCyclicDependencyError(unittest.TestCase): def _makeOne(self, cycles): from pyramid.exceptions import CyclicDependencyError + return CyclicDependencyError(cycles) def test___str__(self): - exc = self._makeOne({'a':['c', 'd'], 'c':['a']}) + exc = self._makeOne({'a': ['c', 'd'], 'c': ['a']}) result = str(exc) self.assertTrue("'a' sorts before ['c', 'd']" in result) self.assertTrue("'c' sorts before ['a']" in result) diff --git a/tests/test_httpexceptions.py b/tests/test_httpexceptions.py index ed6c41e0e..4c13e096d 100644 --- a/tests/test_httpexceptions.py +++ b/tests/test_httpexceptions.py @@ -1,40 +1,45 @@ import unittest -from pyramid.compat import ( - bytes_, - string_types, - text_, - ) +from pyramid.compat import bytes_, string_types, text_ + class Test_exception_response(unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.httpexceptions import exception_response + return exception_response(*arg, **kw) def test_status_400(self): from pyramid.httpexceptions import HTTPBadRequest + self.assertTrue(isinstance(self._callFUT(400), HTTPBadRequest)) def test_status_404(self): from pyramid.httpexceptions import HTTPNotFound + self.assertTrue(isinstance(self._callFUT(404), HTTPNotFound)) def test_status_500(self): from pyramid.httpexceptions import HTTPInternalServerError - self.assertTrue(isinstance(self._callFUT(500), - HTTPInternalServerError)) + + self.assertTrue( + isinstance(self._callFUT(500), HTTPInternalServerError) + ) def test_status_201(self): from pyramid.httpexceptions import HTTPCreated + self.assertTrue(isinstance(self._callFUT(201), HTTPCreated)) def test_extra_kw(self): resp = self._callFUT(404, headers=[('abc', 'def')]) self.assertEqual(resp.headers['abc'], 'def') + class Test_default_exceptionresponse_view(unittest.TestCase): def _callFUT(self, context, request): from pyramid.httpexceptions import default_exceptionresponse_view + return default_exceptionresponse_view(context, request) def test_call_with_exception(self): @@ -49,9 +54,11 @@ class Test_default_exceptionresponse_view(unittest.TestCase): result = self._callFUT(None, request) self.assertEqual(result, context) + class Test__no_escape(unittest.TestCase): def _callFUT(self, val): from pyramid.httpexceptions import _no_escape + return _no_escape(val) def test_null(self): @@ -64,19 +71,29 @@ class Test__no_escape(unittest.TestCase): class DummyUnicodeObject(object): def __unicode__(self): return text_('42') + duo = DummyUnicodeObject() self.assertEqual(self._callFUT(duo), text_('42')) + class TestHTTPException(unittest.TestCase): def _getTargetClass(self): from pyramid.httpexceptions import HTTPException + return HTTPException - def _getTargetSubclass(self, code='200', title='OK', - explanation='explanation', empty_body=False): + def _getTargetSubclass( + self, + code='200', + title='OK', + explanation='explanation', + empty_body=False, + ): cls = self._getTargetClass() + class Subclass(cls): pass + Subclass.empty_body = empty_body Subclass.code = code Subclass.title = title @@ -89,21 +106,25 @@ class TestHTTPException(unittest.TestCase): def test_implements_IResponse(self): from pyramid.interfaces import IResponse + cls = self._getTargetClass() self.assertTrue(IResponse.implementedBy(cls)) def test_provides_IResponse(self): from pyramid.interfaces import IResponse + inst = self._getTargetClass()() self.assertTrue(IResponse.providedBy(inst)) def test_implements_IExceptionResponse(self): from pyramid.interfaces import IExceptionResponse + cls = self._getTargetClass() self.assertTrue(IExceptionResponse.implementedBy(cls)) def test_provides_IExceptionResponse(self): from pyramid.interfaces import IExceptionResponse + inst = self._getTargetClass()() self.assertTrue(IExceptionResponse.providedBy(inst)) @@ -130,7 +151,8 @@ class TestHTTPException(unittest.TestCase): def test_ctor_sets_body_template_obj(self): exc = self._makeOne(body_template='${foo}') self.assertEqual( - exc.body_template_obj.substitute({'foo': 'foo'}), 'foo') + exc.body_template_obj.substitute({'foo': 'foo'}), 'foo' + ) def test_ctor_with_empty_body(self): cls = self._getTargetSubclass(empty_body=True) @@ -323,17 +345,20 @@ class TestHTTPException(unittest.TestCase): start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] import json + retval = json.loads(body.decode('UTF-8')) self.assertEqual(retval['code'], '200 OK') self.assertEqual(retval['title'], 'OK') def test__default_app_iter_with_custom_json(self): def json_formatter(status, body, title, environ): - return {'message': body, - 'code': status, - 'title': title, - 'custom': environ['CUSTOM_VARIABLE'] - } + return { + 'message': body, + 'code': status, + 'title': title, + 'custom': environ['CUSTOM_VARIABLE'], + } + cls = self._getTargetSubclass() exc = cls(comment='comment', json_formatter=json_formatter) environ = _makeEnviron() @@ -342,6 +367,7 @@ class TestHTTPException(unittest.TestCase): start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] import json + retval = json.loads(body.decode('UTF-8')) self.assertEqual(retval['code'], '200 OK') self.assertEqual(retval['title'], 'OK') @@ -359,9 +385,11 @@ class TestHTTPException(unittest.TestCase): cls = self._getTargetSubclass() exc = cls(body_template='${REQUEST_METHOD}') environ = _makeEnviron() + class Choke(object): def __str__(self): # pragma no cover raise ValueError + environ['gardentheory.user'] = Choke() start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] @@ -384,6 +412,7 @@ class TestHTTPException(unittest.TestCase): class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): def _doit(self, content_type): from pyramid.httpexceptions import status_map + L = [] self.assertTrue(status_map) for v in status_map.values(): @@ -405,9 +434,11 @@ class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): def test_it_html(self): self._doit('text/html') + class Test_HTTPMove(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.httpexceptions import _HTTPMove + return _HTTPMove(*arg, **kw) def test_it_location_none_valueerrors(self): @@ -433,13 +464,19 @@ class Test_HTTPMove(unittest.TestCase): environ = _makeEnviron() start_response = DummyStartResponse() app_iter = exc(environ, start_response) - self.assertEqual(app_iter[0], - (b'520 Unknown Error\n\nThe resource has been moved to foo; ' - b'you should be redirected automatically.\n\n')) + self.assertEqual( + app_iter[0], + ( + b'520 Unknown Error\n\nThe resource has been moved to foo; ' + b'you should be redirected automatically.\n\n' + ), + ) + class TestHTTPForbidden(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.httpexceptions import HTTPForbidden + return HTTPForbidden(*arg, **kw) def test_it_result_not_passed(self): @@ -450,9 +487,11 @@ class TestHTTPForbidden(unittest.TestCase): exc = self._makeOne(result='foo') self.assertEqual(exc.result, 'foo') + class TestHTTPMethodNotAllowed(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.httpexceptions import HTTPMethodNotAllowed + return HTTPMethodNotAllowed(*arg, **kw) def test_it_with_default_body_tmpl(self): @@ -460,23 +499,31 @@ class TestHTTPMethodNotAllowed(unittest.TestCase): environ = _makeEnviron() start_response = DummyStartResponse() app_iter = exc(environ, start_response) - self.assertEqual(app_iter[0], - (b'405 Method Not Allowed\n\nThe method GET is not ' - b'allowed for this resource. \n\n\n')) + self.assertEqual( + app_iter[0], + ( + b'405 Method Not Allowed\n\nThe method GET is not ' + b'allowed for this resource. \n\n\n' + ), + ) class DummyRequest(object): exception = None + class DummyStartResponse(object): def __call__(self, status, headerlist): self.status = status self.headerlist = headerlist + def _makeEnviron(**kw): - environ = {'REQUEST_METHOD': 'GET', - 'wsgi.url_scheme': 'http', - 'SERVER_NAME': 'localhost', - 'SERVER_PORT': '80'} + environ = { + 'REQUEST_METHOD': 'GET', + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'localhost', + 'SERVER_PORT': '80', + } environ.update(kw) return environ diff --git a/tests/test_i18n.py b/tests/test_i18n.py index d72d0d480..a830b8e0f 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -8,9 +8,11 @@ localedir = os.path.join(here, 'pkgs', 'localeapp', 'locale') import unittest from pyramid import testing + class TestTranslationString(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.i18n import TranslationString + return TranslationString(*arg, **kw) def test_it(self): @@ -19,9 +21,11 @@ class TestTranslationString(unittest.TestCase): ts = self._makeOne('a') self.assertEqual(ts, 'a') + class TestTranslationStringFactory(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.i18n import TranslationStringFactory + return TranslationStringFactory(*arg, **kw) def test_it(self): @@ -30,9 +34,11 @@ class TestTranslationStringFactory(unittest.TestCase): factory = self._makeOne('a') self.assertEqual(factory('').domain, 'a') + class TestLocalizer(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.i18n import Localizer + return Localizer(*arg, **kw) def test_ctor(self): @@ -43,30 +49,34 @@ class TestLocalizer(unittest.TestCase): def test_translate(self): translations = DummyTranslations() localizer = self._makeOne(None, translations) - self.assertEqual(localizer.translate('123', domain='1', - mapping={}), '123') + self.assertEqual( + localizer.translate('123', domain='1', mapping={}), '123' + ) self.assertTrue(localizer.translator) def test_pluralize(self): translations = DummyTranslations() localizer = self._makeOne(None, translations) - result = localizer.pluralize('singular', 'plural', 1, - domain='1', mapping={}) + result = localizer.pluralize( + 'singular', 'plural', 1, domain='1', mapping={} + ) self.assertEqual(result, 'singular') self.assertTrue(localizer.pluralizer) def test_pluralize_pluralizer_already_added(self): translations = DummyTranslations() localizer = self._makeOne(None, translations) + def pluralizer(*arg, **kw): return arg, kw + localizer.pluralizer = pluralizer - result = localizer.pluralize('singular', 'plural', 1, domain='1', - mapping={}) + result = localizer.pluralize( + 'singular', 'plural', 1, domain='1', mapping={} + ) self.assertEqual( - result, - (('singular', 'plural', 1), {'domain': '1', 'mapping': {}}) - ) + result, (('singular', 'plural', 1), {'domain': '1', 'mapping': {}}) + ) self.assertTrue(localizer.pluralizer is pluralizer) def test_pluralize_default_translations(self): @@ -75,13 +85,16 @@ class TestLocalizer(unittest.TestCase): # "translations object has no attr 'plural' error; see # see https://github.com/Pylons/pyramid/issues/235 from pyramid.i18n import Translations + translations = Translations() translations._catalog = {} localizer = self._makeOne(None, translations) - result = localizer.pluralize('singular', 'plural', 2, domain='1', - mapping={}) + result = localizer.pluralize( + 'singular', 'plural', 2, domain='1', mapping={} + ) self.assertEqual(result, 'plural') + class Test_negotiate_locale_name(unittest.TestCase): def setUp(self): testing.setUp() @@ -91,12 +104,15 @@ class Test_negotiate_locale_name(unittest.TestCase): def _callFUT(self, request): from pyramid.i18n import negotiate_locale_name + return negotiate_locale_name(request) def _registerImpl(self, impl): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() from pyramid.interfaces import ILocaleNegotiator + registry.registerUtility(impl, ILocaleNegotiator) def test_no_registry_on_request(self): @@ -107,6 +123,7 @@ class Test_negotiate_locale_name(unittest.TestCase): def test_with_registry_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() self._registerImpl(dummy_negotiator) request = DummyRequest() @@ -116,8 +133,9 @@ class Test_negotiate_locale_name(unittest.TestCase): def test_default_from_settings(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() - settings = {'default_locale_name':'settings'} + settings = {'default_locale_name': 'settings'} registry.settings = settings request = DummyRequest() request.registry = registry @@ -126,6 +144,7 @@ class Test_negotiate_locale_name(unittest.TestCase): def test_use_default_locale_negotiator(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = DummyRequest() request.registry = registry @@ -138,6 +157,7 @@ class Test_negotiate_locale_name(unittest.TestCase): result = self._callFUT(request) self.assertEqual(result, 'en') + class Test_get_locale_name(unittest.TestCase): def setUp(self): testing.setUp() @@ -147,6 +167,7 @@ class Test_get_locale_name(unittest.TestCase): def _callFUT(self, request): from pyramid.i18n import get_locale_name + return get_locale_name(request) def test_name_on_request(self): @@ -155,6 +176,7 @@ class Test_get_locale_name(unittest.TestCase): result = self._callFUT(request) self.assertEqual(result, 'ie') + class Test_make_localizer(unittest.TestCase): def setUp(self): testing.setUp() @@ -164,47 +186,54 @@ class Test_make_localizer(unittest.TestCase): def _callFUT(self, locale, tdirs): from pyramid.i18n import make_localizer + return make_localizer(locale, tdirs) def test_locale_from_mo(self): from pyramid.i18n import Localizer + localedirs = [localedir] locale_name = 'de' result = self._callFUT(locale_name, localedirs) self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Genehmigen') + self.assertEqual( + result.translate('Approve', 'deformsite'), 'Genehmigen' + ) self.assertEqual(result.translate('Approve'), 'Approve') self.assertTrue(hasattr(result, 'pluralize')) def test_locale_from_mo_bad_mo(self): from pyramid.i18n import Localizer + localedirs = [localedir] locale_name = 'be' result = self._callFUT(locale_name, localedirs) self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Approve') + self.assertEqual(result.translate('Approve', 'deformsite'), 'Approve') def test_locale_from_mo_mo_isdir(self): from pyramid.i18n import Localizer + localedirs = [localedir] locale_name = 'gb' result = self._callFUT(locale_name, localedirs) self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Approve') + self.assertEqual(result.translate('Approve', 'deformsite'), 'Approve') def test_territory_fallback(self): from pyramid.i18n import Localizer + localedirs = [localedir] locale_name = 'de_DE' result = self._callFUT(locale_name, localedirs) self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Submit', 'deformsite'), - 'different') # prefer translations from de_DE locale - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Genehmigen') # missing from de_DE locale, but in de + self.assertEqual( + result.translate('Submit', 'deformsite'), 'different' + ) # prefer translations from de_DE locale + self.assertEqual( + result.translate('Approve', 'deformsite'), 'Genehmigen' + ) # missing from de_DE locale, but in de + class Test_get_localizer(unittest.TestCase): def setUp(self): @@ -215,6 +244,7 @@ class Test_get_localizer(unittest.TestCase): def _callFUT(self, request): from pyramid.i18n import get_localizer + return get_localizer(request) def test_it(self): @@ -222,6 +252,7 @@ class Test_get_localizer(unittest.TestCase): request.localizer = 'localizer' self.assertEqual(self._callFUT(request), 'localizer') + class Test_default_locale_negotiator(unittest.TestCase): def setUp(self): testing.setUp() @@ -231,6 +262,7 @@ class Test_default_locale_negotiator(unittest.TestCase): def _callFUT(self, request): from pyramid.i18n import default_locale_negotiator + return default_locale_negotiator(request) def test_from_none(self): @@ -256,23 +288,19 @@ class Test_default_locale_negotiator(unittest.TestCase): result = self._callFUT(request) self.assertEqual(result, 'foo') + class TestTranslations(unittest.TestCase): def _getTargetClass(self): from pyramid.i18n import Translations + return Translations - + def _makeOne(self): - messages1 = [ - ('foo', 'Voh'), - (('foo1', 1), 'Voh1'), - ] - messages2 = [ - ('foo', 'VohD'), - (('foo1', 1), 'VohD1'), - ] + messages1 = [('foo', 'Voh'), (('foo1', 1), 'Voh1')] + messages2 = [('foo', 'VohD'), (('foo1', 1), 'VohD1')] klass = self._getTargetClass() - + translations1 = klass(None, domain='messages') translations1._catalog = dict(messages1) translations1.plural = lambda *arg: 1 @@ -284,12 +312,14 @@ class TestTranslations(unittest.TestCase): def test_load_locales_None(self): import gettext + klass = self._getTargetClass() result = klass.load(localedir, None, domain=None) self.assertEqual(result.__class__, gettext.NullTranslations) def test_load_domain_None(self): import gettext + locales = ['de', 'en'] klass = self._getTargetClass() result = klass.load(localedir, locales, domain=None) @@ -325,8 +355,9 @@ class TestTranslations(unittest.TestCase): def test_merge_gnutranslations_not_translations(self): import gettext + t = gettext.GNUTranslations() - t._catalog = {'a':'b'} + t._catalog = {'a': 'b'} inst = self._makeOne() inst.merge(t) self.assertEqual(inst._catalog['a'], 'b') @@ -406,16 +437,20 @@ class TestTranslations(unittest.TestCase): t = self._makeOne() self.assertEqual(t.dngettext('messages', 'foo1', 'foos1', 1), 'Voh1') self.assertEqual(t.dngettext('messages1', 'foo1', 'foos1', 1), 'VohD1') - + def test_ldngettext(self): t = self._makeOne() self.assertEqual(t.ldngettext('messages', 'foo1', 'foos1', 1), b'Voh1') - self.assertEqual(t.ldngettext('messages1', 'foo1', 'foos1', 1),b'VohD1') + self.assertEqual( + t.ldngettext('messages1', 'foo1', 'foos1', 1), b'VohD1' + ) def test_dungettext(self): t = self._makeOne() self.assertEqual(t.dungettext('messages', 'foo1', 'foos1', 1), 'Voh1') - self.assertEqual(t.dungettext('messages1', 'foo1', 'foos1', 1), 'VohD1') + self.assertEqual( + t.dungettext('messages1', 'foo1', 'foos1', 1), 'VohD1' + ) def test_default_germanic_pluralization(self): t = self._getTargetClass()() @@ -423,6 +458,7 @@ class TestTranslations(unittest.TestCase): result = t.dungettext('messages', 'foo1', 'foos1', 2) self.assertEqual(result, 'foos1') + class TestLocalizerRequestMixin(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -432,6 +468,7 @@ class TestLocalizerRequestMixin(unittest.TestCase): def _makeOne(self): from pyramid.i18n import LocalizerRequestMixin + request = LocalizerRequestMixin() request.registry = self.config.registry request.cookies = {} @@ -441,12 +478,14 @@ class TestLocalizerRequestMixin(unittest.TestCase): def test_default_localizer(self): # `localizer` returns a default localizer for `en` from pyramid.i18n import Localizer + request = self._makeOne() self.assertEqual(request.localizer.__class__, Localizer) self.assertEqual(request.locale_name, 'en') def test_custom_localizer_for_default_locale(self): from pyramid.interfaces import ILocalizer + dummy = object() self.config.registry.registerUtility(dummy, ILocalizer, name='en') request = self._makeOne() @@ -454,6 +493,7 @@ class TestLocalizerRequestMixin(unittest.TestCase): def test_custom_localizer_for_custom_locale(self): from pyramid.interfaces import ILocalizer + dummy = object() self.config.registry.registerUtility(dummy, ILocalizer, name='ie') request = self._makeOne() @@ -463,39 +503,46 @@ class TestLocalizerRequestMixin(unittest.TestCase): def test_localizer_from_mo(self): from pyramid.interfaces import ITranslationDirectories from pyramid.i18n import Localizer + localedirs = [localedir] self.config.registry.registerUtility( - localedirs, ITranslationDirectories) + localedirs, ITranslationDirectories + ) request = self._makeOne() request._LOCALE_ = 'de' result = request.localizer self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Genehmigen') + self.assertEqual( + result.translate('Approve', 'deformsite'), 'Genehmigen' + ) self.assertEqual(result.translate('Approve'), 'Approve') self.assertTrue(hasattr(result, 'pluralize')) def test_localizer_from_mo_bad_mo(self): from pyramid.interfaces import ITranslationDirectories from pyramid.i18n import Localizer + localedirs = [localedir] self.config.registry.registerUtility( - localedirs, ITranslationDirectories) + localedirs, ITranslationDirectories + ) request = self._makeOne() request._LOCALE_ = 'be' result = request.localizer self.assertEqual(result.__class__, Localizer) - self.assertEqual(result.translate('Approve', 'deformsite'), - 'Approve') + self.assertEqual(result.translate('Approve', 'deformsite'), 'Approve') + class DummyRequest(object): def __init__(self): self.params = {} self.cookies = {} + def dummy_negotiator(request): return 'bogus' + class DummyTranslations(object): def ugettext(self, text): return text diff --git a/tests/test_integration.py b/tests/test_integration.py index 741c7599f..250d6790d 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -10,32 +10,33 @@ from pyramid.wsgi import wsgiapp from pyramid.view import view_config from pyramid.static import static_view from pyramid.testing import skip_on -from pyramid.compat import ( - text_, - url_quote, - ) +from pyramid.compat import text_, url_quote from zope.interface import Interface from webtest import TestApp # 5 years from now (more or less) -fiveyrsfuture = datetime.datetime.utcnow() + datetime.timedelta(5*365) +fiveyrsfuture = datetime.datetime.utcnow() + datetime.timedelta(5 * 365) defaultlocale = locale.getdefaultlocale()[1] + class INothing(Interface): pass + @view_config(for_=INothing) @wsgiapp def wsgiapptest(environ, start_response): """ """ return '123' + class WGSIAppPlusViewConfigTests(unittest.TestCase): def test_it(self): from venusian import ATTACH_ATTR import types + self.assertTrue(getattr(wsgiapptest, ATTACH_ATTR)) self.assertTrue(type(wsgiapptest) is types.FunctionType) context = DummyContext() @@ -49,21 +50,27 @@ class WGSIAppPlusViewConfigTests(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.config import Configurator from . import test_integration + config = Configurator() config.scan(test_integration) config.commit() reg = config.registry view = reg.adapters.lookup( - (IViewClassifier, IRequest, INothing), IView, name='') + (IViewClassifier, IRequest, INothing), IView, name='' + ) self.assertEqual(view.__original_view__, wsgiapptest) + class IntegrationBase(object): root_factory = None package = None + def setUp(self): from pyramid.config import Configurator - config = Configurator(root_factory=self.root_factory, - package=self.package) + + config = Configurator( + root_factory=self.root_factory, package=self.package + ) config.include(self.package) app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -72,8 +79,10 @@ class IntegrationBase(object): def tearDown(self): self.config.end() + here = os.path.dirname(__file__) + class StaticAppBase(IntegrationBase): def test_basic(self): res = self.testapp.get('/minimal.txt', status=200) @@ -81,16 +90,18 @@ class StaticAppBase(IntegrationBase): def test_hidden(self): res = self.testapp.get('/static/.hiddenfile', status=200) - _assertBody(res.body, os.path.join(here, 'fixtures/static/.hiddenfile')) + _assertBody( + res.body, os.path.join(here, 'fixtures/static/.hiddenfile') + ) - if defaultlocale is not None: # pragma: no cover + if defaultlocale is not None: # pragma: no cover # These tests are expected to fail on LANG=C systems due to decode # errors and on non-Linux systems due to git highchar handling # vagaries def test_highchars_in_pathelement(self): path = os.path.join( - here, - text_('fixtures/static/héhé/index.html', 'utf-8')) + here, text_('fixtures/static/héhé/index.html', 'utf-8') + ) pathdir = os.path.dirname(path) body = b'<html>hehe</html>\n' try: @@ -106,8 +117,8 @@ class StaticAppBase(IntegrationBase): def test_highchars_in_filename(self): path = os.path.join( - here, - text_('fixtures/static/héhé.html', 'utf-8')) + here, text_('fixtures/static/héhé.html', 'utf-8') + ) body = b'<html>hehe file</html>\n' with open(path, 'wb') as fp: fp.write(body) @@ -120,7 +131,8 @@ class StaticAppBase(IntegrationBase): def test_not_modified(self): self.testapp.extra_environ = { - 'HTTP_IF_MODIFIED_SINCE':httpdate(fiveyrsfuture)} + 'HTTP_IF_MODIFIED_SINCE': httpdate(fiveyrsfuture) + } res = self.testapp.get('/minimal.txt', status=304) self.assertEqual(res.body, b'') @@ -135,14 +147,16 @@ class StaticAppBase(IntegrationBase): def test_directory_noslash_redir_preserves_qs(self): res = self.testapp.get('/static?a=1&b=2', status=301) - self.assertEqual(res.headers['Location'], - 'http://localhost/static/?a=1&b=2') + self.assertEqual( + res.headers['Location'], 'http://localhost/static/?a=1&b=2' + ) def test_directory_noslash_redir_with_scriptname(self): - self.testapp.extra_environ = {'SCRIPT_NAME':'/script_name'} + self.testapp.extra_environ = {'SCRIPT_NAME': '/script_name'} res = self.testapp.get('/static', status=301) - self.assertEqual(res.headers['Location'], - 'http://localhost/script_name/static/') + self.assertEqual( + res.headers['Location'], 'http://localhost/script_name/static/' + ) def test_directory_withslash(self): fn = os.path.join(here, 'fixtures/static/index.html') @@ -150,30 +164,30 @@ class StaticAppBase(IntegrationBase): _assertBody(res.body, fn) def test_range_inclusive(self): - self.testapp.extra_environ = {'HTTP_RANGE':'bytes=1-2'} + self.testapp.extra_environ = {'HTTP_RANGE': 'bytes=1-2'} res = self.testapp.get('/static/index.html', status=206) self.assertEqual(res.body, b'ht') def test_range_tilend(self): - self.testapp.extra_environ = {'HTTP_RANGE':'bytes=-5'} + self.testapp.extra_environ = {'HTTP_RANGE': 'bytes=-5'} res = self.testapp.get('/static/index.html', status=206) self.assertEqual(res.body, b'html>') def test_range_notbytes(self): - self.testapp.extra_environ = {'HTTP_RANGE':'kHz=-5'} + self.testapp.extra_environ = {'HTTP_RANGE': 'kHz=-5'} res = self.testapp.get('/static/index.html', status=200) - _assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody(res.body, os.path.join(here, 'fixtures/static/index.html')) def test_range_multiple(self): - res = self.testapp.get('/static/index.html', - [('HTTP_RANGE', 'bytes=10-11,11-12')], - status=200) - _assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + res = self.testapp.get( + '/static/index.html', + [('HTTP_RANGE', 'bytes=10-11,11-12')], + status=200, + ) + _assertBody(res.body, os.path.join(here, 'fixtures/static/index.html')) def test_range_oob(self): - self.testapp.extra_environ = {'HTTP_RANGE':'bytes=1000-1002'} + self.testapp.extra_environ = {'HTTP_RANGE': 'bytes=1000-1002'} self.testapp.get('/static/index.html', status=416) def test_notfound(self): @@ -188,6 +202,7 @@ class StaticAppBase(IntegrationBase): def test_oob_slash(self): self.testapp.get('/%2F/test_integration.py', status=404) + class TestEventOnlySubscribers(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.eventonly' @@ -197,55 +212,64 @@ class TestEventOnlySubscribers(IntegrationBase, unittest.TestCase): def test_sendfoobar(self): res = self.testapp.get('/sendfoobar', status=200) - self.assertEqual(sorted(res.body.split()), - [b'foobar', b'foobar2', b'foobaryup', b'foobaryup2']) + self.assertEqual( + sorted(res.body.split()), + [b'foobar', b'foobar2', b'foobaryup', b'foobaryup2'], + ) + class TestStaticAppUsingAbsPath(StaticAppBase, unittest.TestCase): package = 'tests.pkgs.static_abspath' + class TestStaticAppUsingAssetSpec(StaticAppBase, unittest.TestCase): package = 'tests.pkgs.static_assetspec' + class TestStaticAppNoSubpath(unittest.TestCase): staticapp = static_view(os.path.join(here, 'fixtures'), use_subpath=False) + def _makeRequest(self, extra): from pyramid.request import Request from io import BytesIO - kw = {'PATH_INFO':'', - 'SCRIPT_NAME':'', - 'SERVER_NAME':'localhost', - 'SERVER_PORT':'80', - 'REQUEST_METHOD':'GET', - 'wsgi.version':(1,0), - 'wsgi.url_scheme':'http', - 'wsgi.input':BytesIO()} + + kw = { + 'PATH_INFO': '', + 'SCRIPT_NAME': '', + 'SERVER_NAME': 'localhost', + 'SERVER_PORT': '80', + 'REQUEST_METHOD': 'GET', + 'wsgi.version': (1, 0), + 'wsgi.url_scheme': 'http', + 'wsgi.input': BytesIO(), + } kw.update(extra) request = Request(kw) return request def test_basic(self): - request = self._makeRequest({'PATH_INFO':'/minimal.txt'}) + request = self._makeRequest({'PATH_INFO': '/minimal.txt'}) context = DummyContext() result = self.staticapp(context, request) self.assertEqual(result.status, '200 OK') _assertBody(result.body, os.path.join(here, 'fixtures/minimal.txt')) + class TestStaticAppWithRoutePrefix(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.static_routeprefix' def test_includelevel1(self): res = self.testapp.get('/static/minimal.txt', status=200) - _assertBody(res.body, - os.path.join(here, 'fixtures/minimal.txt')) + _assertBody(res.body, os.path.join(here, 'fixtures/minimal.txt')) def test_includelevel2(self): res = self.testapp.get('/prefix/static/index.html', status=200) - _assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody(res.body, os.path.join(here, 'fixtures/static/index.html')) class TestFixtureApp(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.fixtureapp' + def test_another(self): res = self.testapp.get('/another.html', status=200) self.assertEqual(res.body, b'fixture') @@ -264,38 +288,45 @@ class TestFixtureApp(IntegrationBase, unittest.TestCase): def test_protected(self): self.testapp.get('/protected.html', status=403) + class TestStaticPermApp(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.staticpermapp' root_factory = 'tests.pkgs.staticpermapp:RootFactory' + def test_allowed(self): result = self.testapp.get('/allowed/index.html', status=200) - _assertBody(result.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody( + result.body, os.path.join(here, 'fixtures/static/index.html') + ) def test_denied_via_acl_global_root_factory(self): - self.testapp.extra_environ = {'REMOTE_USER':'bob'} + self.testapp.extra_environ = {'REMOTE_USER': 'bob'} self.testapp.get('/protected/index.html', status=403) def test_allowed_via_acl_global_root_factory(self): - self.testapp.extra_environ = {'REMOTE_USER':'fred'} + self.testapp.extra_environ = {'REMOTE_USER': 'fred'} result = self.testapp.get('/protected/index.html', status=200) - _assertBody(result.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody( + result.body, os.path.join(here, 'fixtures/static/index.html') + ) def test_denied_via_acl_local_root_factory(self): - self.testapp.extra_environ = {'REMOTE_USER':'fred'} + self.testapp.extra_environ = {'REMOTE_USER': 'fred'} self.testapp.get('/factory_protected/index.html', status=403) def test_allowed_via_acl_local_root_factory(self): - self.testapp.extra_environ = {'REMOTE_USER':'bob'} + self.testapp.extra_environ = {'REMOTE_USER': 'bob'} result = self.testapp.get('/factory_protected/index.html', status=200) - _assertBody(result.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody( + result.body, os.path.join(here, 'fixtures/static/index.html') + ) + class TestCCBug(IntegrationBase, unittest.TestCase): # "unordered" as reported in IRC by author of # http://labs.creativecommons.org/2010/01/13/cc-engine-and-web-non-frameworks/ package = 'tests.pkgs.ccbugapp' + def test_rdf(self): res = self.testapp.get('/licenses/1/v1/rdf', status=200) self.assertEqual(res.body, b'rdf') @@ -304,11 +335,13 @@ class TestCCBug(IntegrationBase, unittest.TestCase): res = self.testapp.get('/licenses/1/v1/juri', status=200) self.assertEqual(res.body, b'juri') + class TestHybridApp(IntegrationBase, unittest.TestCase): # make sure views registered for a route "win" over views registered # without one, even though the context of the non-route view may # be more specific than the route view. package = 'tests.pkgs.hybridapp' + def test_root(self): res = self.testapp.get('/', status=200) self.assertEqual(res.body, b'global') @@ -347,27 +380,34 @@ class TestHybridApp(IntegrationBase, unittest.TestCase): res = self.testapp.get('/error_sub', status=200) self.assertEqual(res.body, b'supressed2') + class TestRestBugApp(IntegrationBase, unittest.TestCase): # test bug reported by delijati 2010/2/3 (http://pastebin.com/d4cc15515) package = 'tests.pkgs.restbugapp' + def test_it(self): res = self.testapp.get('/pet', status=200) self.assertEqual(res.body, b'gotten') + class TestForbiddenAppHasResult(IntegrationBase, unittest.TestCase): # test that forbidden exception has ACLDenied result attached package = 'tests.pkgs.forbiddenapp' + def test_it(self): res = self.testapp.get('/x', status=403) message, result = [x.strip() for x in res.body.split(b'\n')] self.assertTrue(message.endswith(b'failed permission check')) self.assertTrue( - result.startswith(b"ACLDenied permission 'private' via ACE " - b"'<default deny>' in ACL " - b"'<No ACL found on any object in resource " - b"lineage>' on context")) - self.assertTrue( - result.endswith(b"for principals ['system.Everyone']")) + result.startswith( + b"ACLDenied permission 'private' via ACE " + b"'<default deny>' in ACL " + b"'<No ACL found on any object in resource " + b"lineage>' on context" + ) + ) + self.assertTrue(result.endswith(b"for principals ['system.Everyone']")) + class TestViewDecoratorApp(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.viewdecoratorapp' @@ -380,6 +420,7 @@ class TestViewDecoratorApp(IntegrationBase, unittest.TestCase): res = self.testapp.get('/second', status=200) self.assertTrue(b'OK2' in res.body) + class TestNotFoundView(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.notfoundview' @@ -397,6 +438,7 @@ class TestNotFoundView(IntegrationBase, unittest.TestCase): res = self.testapp.get('/baz', status=200) self.assertTrue(b'baz_notfound' in res.body) + class TestForbiddenView(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.forbiddenview' @@ -405,10 +447,12 @@ class TestForbiddenView(IntegrationBase, unittest.TestCase): self.assertTrue(b'foo_forbidden' in res.body) res = self.testapp.get('/bar', status=200) self.assertTrue(b'generic_forbidden' in res.body) - + + class TestViewPermissionBug(IntegrationBase, unittest.TestCase): # view_execution_permitted bug as reported by Shane at http://lists.repoze.org/pipermail/repoze-dev/2010-October/003603.html package = 'tests.pkgs.permbugapp' + def test_test(self): res = self.testapp.get('/test', status=200) self.assertTrue(b'ACLDenied' in res.body) @@ -416,9 +460,11 @@ class TestViewPermissionBug(IntegrationBase, unittest.TestCase): def test_x(self): self.testapp.get('/x', status=403) + class TestDefaultViewPermissionBug(IntegrationBase, unittest.TestCase): # default_view_permission bug as reported by Wiggy at http://lists.repoze.org/pipermail/repoze-dev/2010-October/003602.html package = 'tests.pkgs.defpermbugapp' + def test_x(self): res = self.testapp.get('/x', status=403) self.assertTrue(b'failed permission check' in res.body) @@ -431,13 +477,16 @@ class TestDefaultViewPermissionBug(IntegrationBase, unittest.TestCase): res = self.testapp.get('/z', status=200) self.assertTrue(b'public' in res.body) + from .pkgs.exceptionviewapp.models import AnException, NotAnException -excroot = {'anexception':AnException(), - 'notanexception':NotAnException()} + +excroot = {'anexception': AnException(), 'notanexception': NotAnException()} + class TestExceptionViewsApp(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.exceptionviewapp' root_factory = lambda *arg: excroot + def test_root(self): res = self.testapp.get('/', status=200) self.assertTrue(b'maybe' in res.body) @@ -469,11 +518,14 @@ class TestExceptionViewsApp(IntegrationBase, unittest.TestCase): def test_raise_httpexception(self): res = self.testapp.get('/route_raise_httpexception', status=200) self.assertTrue(b'caught' in res.body) - + + class TestConflictApp(unittest.TestCase): package = 'tests.pkgs.conflictapp' + def _makeConfig(self): from pyramid.config import Configurator + config = Configurator() return config @@ -489,10 +541,13 @@ class TestConflictApp(unittest.TestCase): def test_overridden_autoresolved_view(self): from pyramid.response import Response + config = self._makeConfig() config.include(self.package) + def thisview(request): return Response('this view') + config.add_view(thisview) app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -501,10 +556,13 @@ class TestConflictApp(unittest.TestCase): def test_overridden_route_view(self): from pyramid.response import Response + config = self._makeConfig() config.include(self.package) + def thisview(request): return Response('this view') + config.add_view(thisview, route_name='aroute') app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -523,6 +581,7 @@ class TestConflictApp(unittest.TestCase): config = self._makeConfig() config.include(self.package) from pyramid.testing import DummySecurityPolicy + config.set_authorization_policy(DummySecurityPolicy('fred')) config.set_authentication_policy(DummySecurityPolicy(permissive=True)) app = config.make_wsgi_app() @@ -530,11 +589,14 @@ class TestConflictApp(unittest.TestCase): res = self.testapp.get('/protected', status=200) self.assertTrue('protected view' in res) + class ImperativeIncludeConfigurationTest(unittest.TestCase): def setUp(self): from pyramid.config import Configurator + config = Configurator() from .pkgs.includeapp1.root import configure + configure(config) app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -555,9 +617,11 @@ class ImperativeIncludeConfigurationTest(unittest.TestCase): res = self.testapp.get('/three', status=200) self.assertTrue(b'three' in res.body) + class SelfScanAppTest(unittest.TestCase): def setUp(self): from .test_config.pkgs.selfscan import main + config = main() app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -574,9 +638,11 @@ class SelfScanAppTest(unittest.TestCase): res = self.testapp.get('/two', status=200) self.assertTrue(b'two' in res.body) + class WSGIApp2AppTest(unittest.TestCase): def setUp(self): from .pkgs.wsgiapp2app import main + config = main() app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -589,9 +655,11 @@ class WSGIApp2AppTest(unittest.TestCase): res = self.testapp.get('/hello', status=200) self.assertTrue(b'Hello' in res.body) + class SubrequestAppTest(unittest.TestCase): def setUp(self): from .pkgs.subrequestapp import main + config = main() app = config.make_wsgi_app() self.testapp = TestApp(app) @@ -612,8 +680,10 @@ class SubrequestAppTest(unittest.TestCase): res = self.testapp.get('/view_five', status=200) self.assertTrue(b'Value error raised' in res.body) + class RendererScanAppTest(IntegrationBase, unittest.TestCase): package = 'tests.pkgs.rendererscanapp' + def test_root(self): res = self.testapp.get('/one', status=200) self.assertTrue(b'One!' in res.body) @@ -631,9 +701,11 @@ class RendererScanAppTest(IntegrationBase, unittest.TestCase): res = testapp.get('/two', status=200) self.assertTrue(b'Two!' in res.body) + class UnicodeInURLTest(unittest.TestCase): def _makeConfig(self): from pyramid.config import Configurator + config = Configurator() return config @@ -643,7 +715,9 @@ class UnicodeInURLTest(unittest.TestCase): def test_unicode_in_url_404(self): request_path = '/avalia%C3%A7%C3%A3o_participante' - request_path_unicode = b'/avalia\xc3\xa7\xc3\xa3o_participante'.decode('utf-8') + request_path_unicode = b'/avalia\xc3\xa7\xc3\xa3o_participante'.decode( + 'utf-8' + ) config = self._makeConfig() testapp = self._makeTestApp(config) @@ -657,7 +731,9 @@ class UnicodeInURLTest(unittest.TestCase): def test_unicode_in_url_200(self): request_path = '/avalia%C3%A7%C3%A3o_participante' - request_path_unicode = b'/avalia\xc3\xa7\xc3\xa3o_participante'.decode('utf-8') + request_path_unicode = b'/avalia\xc3\xa7\xc3\xa3o_participante'.decode( + 'utf-8' + ) def myview(request): return 'XXX' @@ -676,18 +752,31 @@ class AcceptContentTypeTest(unittest.TestCase): def _makeConfig(self): def hello_view(request): return {'message': 'Hello!'} + from pyramid.config import Configurator + config = Configurator() config.add_route('hello', '/hello') - config.add_view(hello_view, route_name='hello', - accept='text/plain', renderer='string') - config.add_view(hello_view, route_name='hello', - accept='application/json', renderer='json') + config.add_view( + hello_view, + route_name='hello', + accept='text/plain', + renderer='string', + ) + config.add_view( + hello_view, + route_name='hello', + accept='application/json', + renderer='json', + ) + def hello_fallback_view(request): request.response.content_type = 'text/x-fallback' return 'hello fallback' - config.add_view(hello_fallback_view, route_name='hello', - renderer='string') + + config.add_view( + hello_fallback_view, route_name='hello', renderer='string' + ) return config def _makeTestApp(self, config): @@ -696,36 +785,49 @@ class AcceptContentTypeTest(unittest.TestCase): def tearDown(self): import pyramid.config + pyramid.config.global_registries.empty() def test_client_side_ordering(self): config = self._makeConfig() app = self._makeTestApp(config) - res = app.get('/hello', headers={ - 'Accept': 'application/json; q=1.0, text/plain; q=0.9', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'application/json; q=1.0, text/plain; q=0.9'}, + status=200, + ) self.assertEqual(res.content_type, 'application/json') - res = app.get('/hello', headers={ - 'Accept': 'text/plain; q=0.9, application/json; q=1.0', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'text/plain; q=0.9, application/json; q=1.0'}, + status=200, + ) self.assertEqual(res.content_type, 'application/json') - res = app.get('/hello', headers={'Accept': 'application/*'}, status=200) + res = app.get( + '/hello', headers={'Accept': 'application/*'}, status=200 + ) self.assertEqual(res.content_type, 'application/json') res = app.get('/hello', headers={'Accept': 'text/*'}, status=200) self.assertEqual(res.content_type, 'text/plain') - res = app.get('/hello', headers={'Accept': 'something/else'}, status=200) + res = app.get( + '/hello', headers={'Accept': 'something/else'}, status=200 + ) self.assertEqual(res.content_type, 'text/x-fallback') def test_default_server_side_ordering(self): config = self._makeConfig() app = self._makeTestApp(config) - res = app.get('/hello', headers={ - 'Accept': 'application/json, text/plain', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'application/json, text/plain'}, + status=200, + ) self.assertEqual(res.content_type, 'text/plain') - res = app.get('/hello', headers={ - 'Accept': 'text/plain, application/json', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'text/plain, application/json'}, + status=200, + ) self.assertEqual(res.content_type, 'text/plain') res = app.get('/hello', headers={'Accept': '*/*'}, status=200) self.assertEqual(res.content_type, 'text/plain') @@ -733,21 +835,28 @@ class AcceptContentTypeTest(unittest.TestCase): self.assertEqual(res.content_type, 'text/plain') res = app.get('/hello', headers={'Accept': 'invalid'}, status=200) self.assertEqual(res.content_type, 'text/plain') - res = app.get('/hello', headers={'Accept': 'something/else'}, status=200) + res = app.get( + '/hello', headers={'Accept': 'something/else'}, status=200 + ) self.assertEqual(res.content_type, 'text/x-fallback') def test_custom_server_side_ordering(self): config = self._makeConfig() config.add_accept_view_order( - 'application/json', weighs_more_than='text/plain') + 'application/json', weighs_more_than='text/plain' + ) app = self._makeTestApp(config) - res = app.get('/hello', headers={ - 'Accept': 'application/json, text/plain', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'application/json, text/plain'}, + status=200, + ) self.assertEqual(res.content_type, 'application/json') - res = app.get('/hello', headers={ - 'Accept': 'text/plain, application/json', - }, status=200) + res = app.get( + '/hello', + headers={'Accept': 'text/plain, application/json'}, + status=200, + ) self.assertEqual(res.content_type, 'application/json') res = app.get('/hello', headers={'Accept': '*/*'}, status=200) self.assertEqual(res.content_type, 'application/json') @@ -755,7 +864,9 @@ class AcceptContentTypeTest(unittest.TestCase): self.assertEqual(res.content_type, 'application/json') res = app.get('/hello', headers={'Accept': 'invalid'}, status=200) self.assertEqual(res.content_type, 'application/json') - res = app.get('/hello', headers={'Accept': 'something/else'}, status=200) + res = app.get( + '/hello', headers={'Accept': 'something/else'}, status=200 + ) self.assertEqual(res.content_type, 'text/x-fallback') def test_deprecated_ranges_in_route_predicate(self): @@ -763,53 +874,66 @@ class AcceptContentTypeTest(unittest.TestCase): config.add_route('foo', '/foo', accept='text/*') config.add_view(lambda r: 'OK', route_name='foo', renderer='string') app = self._makeTestApp(config) - res = app.get('/foo', headers={ - 'Accept': 'application/json; q=1.0, text/plain; q=0.9', - }, status=200) + res = app.get( + '/foo', + headers={'Accept': 'application/json; q=1.0, text/plain; q=0.9'}, + status=200, + ) self.assertEqual(res.content_type, 'text/plain') self.assertEqual(res.body, b'OK') - res = app.get('/foo', headers={ - 'Accept': 'application/json', - }, status=404) + res = app.get( + '/foo', headers={'Accept': 'application/json'}, status=404 + ) self.assertEqual(res.content_type, 'application/json') def test_deprecated_ranges_in_view_predicate(self): config = self._makeConfig() config.add_route('foo', '/foo') - config.add_view(lambda r: 'OK', route_name='foo', - accept='text/*', renderer='string') + config.add_view( + lambda r: 'OK', + route_name='foo', + accept='text/*', + renderer='string', + ) app = self._makeTestApp(config) - res = app.get('/foo', headers={ - 'Accept': 'application/json; q=1.0, text/plain; q=0.9', - }, status=200) + res = app.get( + '/foo', + headers={'Accept': 'application/json; q=1.0, text/plain; q=0.9'}, + status=200, + ) self.assertEqual(res.content_type, 'text/plain') self.assertEqual(res.body, b'OK') - res = app.get('/foo', headers={ - 'Accept': 'application/json', - }, status=404) + res = app.get( + '/foo', headers={'Accept': 'application/json'}, status=404 + ) self.assertEqual(res.content_type, 'application/json') class DummyContext(object): pass + class DummyRequest: subpath = ('__init__.py',) traversed = None - environ = {'REQUEST_METHOD':'GET', 'wsgi.version':(1,0)} + environ = {'REQUEST_METHOD': 'GET', 'wsgi.version': (1, 0)} + def get_response(self, application): return application(None, None) + def httpdate(ts): return ts.strftime("%a, %d %b %Y %H:%M:%S GMT") + def read_(filename): with open(filename, 'rb') as fp: val = fp.read() return val - + + def _assertBody(body, filename): - if defaultlocale is None: # pragma: no cover + if defaultlocale is None: # pragma: no cover # If system locale does not have an encoding then default to utf-8 filename = filename.encode('utf-8') # strip both \n and \r for windows @@ -818,13 +942,13 @@ def _assertBody(body, filename): data = read_(filename) data = data.replace(b'\r', b'') data = data.replace(b'\n', b'') - assert(body == data) + assert body == data class MemoryLeaksTest(unittest.TestCase): - def tearDown(self): import pyramid.config + pyramid.config.global_registries.empty() def get_gc_count(self): @@ -839,6 +963,7 @@ class MemoryLeaksTest(unittest.TestCase): @skip_on('pypy') def test_memory_leaks(self): from pyramid.config import Configurator + Configurator().make_wsgi_app() # Initialize all global objects initial_count = self.get_gc_count() diff --git a/tests/test_location.py b/tests/test_location.py index e1f47f4ab..b48b7bdaa 100644 --- a/tests/test_location.py +++ b/tests/test_location.py @@ -1,15 +1,20 @@ import unittest + class TestInside(unittest.TestCase): def _callFUT(self, one, two): from pyramid.location import inside + return inside(one, two) - + def test_inside(self): o1 = Location() - o2 = Location(); o2.__parent__ = o1 - o3 = Location(); o3.__parent__ = o2 - o4 = Location(); o4.__parent__ = o3 + o2 = Location() + o2.__parent__ = o1 + o3 = Location() + o3.__parent__ = o2 + o4 = Location() + o4.__parent__ = o3 self.assertEqual(self._callFUT(o1, o1), True) self.assertEqual(self._callFUT(o2, o1), True) @@ -18,23 +23,31 @@ class TestInside(unittest.TestCase): self.assertEqual(self._callFUT(o1, o4), False) self.assertEqual(self._callFUT(o1, None), False) + class TestLineage(unittest.TestCase): def _callFUT(self, context): from pyramid.location import lineage + return lineage(context) def test_lineage(self): o1 = Location() - o2 = Location(); o2.__parent__ = o1 - o3 = Location(); o3.__parent__ = o2 - o4 = Location(); o4.__parent__ = o3 + o2 = Location() + o2.__parent__ = o1 + o3 = Location() + o3.__parent__ = o2 + o4 = Location() + o4.__parent__ = o3 result = list(self._callFUT(o3)) self.assertEqual(result, [o3, o2, o1]) result = list(self._callFUT(o1)) self.assertEqual(result, [o1]) + from pyramid.interfaces import ILocation from zope.interface import implementer + + @implementer(ILocation) class Location(object): __name__ = __parent__ = None diff --git a/tests/test_paster.py b/tests/test_paster.py index dd296d03e..dd53195c7 100644 --- a/tests/test_paster.py +++ b/tests/test_paster.py @@ -4,15 +4,18 @@ from .test_scripts.dummy import DummyLoader here = os.path.dirname(__file__) + class Test_get_app(unittest.TestCase): def _callFUT(self, config_file, section_name, options=None, _loader=None): import pyramid.paster + old_loader = pyramid.paster.get_config_loader try: if _loader is not None: pyramid.paster.get_config_loader = _loader - return pyramid.paster.get_app(config_file, section_name, - options=options) + return pyramid.paster.get_app( + config_file, section_name, options=options + ) finally: pyramid.paster.get_config_loader = old_loader @@ -20,8 +23,8 @@ class Test_get_app(unittest.TestCase): app = DummyApp() loader = DummyLoader(app=app) result = self._callFUT( - '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'}, - _loader=loader) + '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'}, _loader=loader + ) self.assertEqual(loader.uri.path, '/foo/bar/myapp.ini') self.assertEqual(len(loader.calls), 1) self.assertEqual(loader.calls[0]['op'], 'app') @@ -33,18 +36,23 @@ class Test_get_app(unittest.TestCase): options = {'bar': 'baz'} app = self._callFUT( os.path.join(here, 'fixtures', 'dummy.ini'), - 'myapp', options=options) + 'myapp', + options=options, + ) self.assertEqual(app.settings['foo'], 'baz') + class Test_get_appsettings(unittest.TestCase): def _callFUT(self, config_file, section_name, options=None, _loader=None): import pyramid.paster + old_loader = pyramid.paster.get_config_loader try: if _loader is not None: pyramid.paster.get_config_loader = _loader - return pyramid.paster.get_appsettings(config_file, section_name, - options=options) + return pyramid.paster.get_appsettings( + config_file, section_name, options=options + ) finally: pyramid.paster.get_config_loader = old_loader @@ -52,8 +60,8 @@ class Test_get_appsettings(unittest.TestCase): values = {'a': 1} loader = DummyLoader(app_settings=values) result = self._callFUT( - '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'}, - _loader=loader) + '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'}, _loader=loader + ) self.assertEqual(loader.uri.path, '/foo/bar/myapp.ini') self.assertEqual(len(loader.calls), 1) self.assertEqual(loader.calls[0]['op'], 'app_settings') @@ -65,12 +73,16 @@ class Test_get_appsettings(unittest.TestCase): options = {'bar': 'baz'} result = self._callFUT( os.path.join(here, 'fixtures', 'dummy.ini'), - 'myapp', options=options) + 'myapp', + options=options, + ) self.assertEqual(result['foo'], 'baz') + class Test_setup_logging(unittest.TestCase): def _callFUT(self, config_file, global_conf=None, _loader=None): import pyramid.paster + old_loader = pyramid.paster.get_config_loader try: if _loader is not None: @@ -103,13 +115,16 @@ class Test_setup_logging(unittest.TestCase): self.assertEqual(loader.calls[0]['op'], 'logging') self.assertEqual(loader.calls[0]['defaults'], {'key': 'val'}) + class Test_bootstrap(unittest.TestCase): def _callFUT(self, config_uri, request=None): from pyramid.paster import bootstrap + return bootstrap(config_uri, request) def setUp(self): import pyramid.paster + self.original_get_app = pyramid.paster.get_app self.original_prepare = pyramid.paster.prepare self.app = app = DummyApp() @@ -120,17 +135,20 @@ class Test_bootstrap(unittest.TestCase): self.a = a self.kw = kw return app + self.get_app = pyramid.paster.get_app = DummyGetApp() class DummyPrepare(object): def __call__(self, *a, **kw): self.a = a self.kw = kw - return {'root':root, 'closer':lambda: None} + return {'root': root, 'closer': lambda: None} + self.getroot = pyramid.paster.prepare = DummyPrepare() def tearDown(self): import pyramid.paster + pyramid.paster.get_app = self.original_get_app pyramid.paster.prepare = self.original_prepare @@ -142,27 +160,34 @@ class Test_bootstrap(unittest.TestCase): self.assertEqual(result['root'], self.root) self.assertTrue('closer' in result) + class Dummy: pass + class DummyRegistry(object): settings = {} + dummy_registry = DummyRegistry() + class DummyApp: def __init__(self): self.registry = dummy_registry + def make_dummyapp(global_conf, **settings): app = DummyApp() app.settings = settings app.global_conf = global_conf return app + class DummyRequest: application_url = 'http://example.com:5432' script_name = '' + def __init__(self, environ): self.environ = environ self.matchdict = {} diff --git a/tests/test_path.py b/tests/test_path.py index 4ab314f17..626bb1139 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -4,14 +4,17 @@ from pyramid.compat import PY2 here = os.path.abspath(os.path.dirname(__file__)) + class TestCallerPath(unittest.TestCase): def tearDown(self): from . import test_path + if hasattr(test_path, '__abspath__'): del test_path.__abspath__ def _callFUT(self, path, level=2): from pyramid.path import caller_path + return caller_path(path, level) def test_isabs(self): @@ -20,12 +23,14 @@ class TestCallerPath(unittest.TestCase): def test_pkgrelative(self): import os + result = self._callFUT('a/b/c') self.assertEqual(result, os.path.join(here, 'a/b/c')) def test_memoization_has_abspath(self): import os from . import test_path + test_path.__abspath__ = '/foo/bar' result = self._callFUT('a/b/c') self.assertEqual(result, os.path.join('/foo/bar', 'a/b/c')) @@ -33,37 +38,46 @@ class TestCallerPath(unittest.TestCase): def test_memoization_success(self): import os from . import test_path + result = self._callFUT('a/b/c') self.assertEqual(result, os.path.join(here, 'a/b/c')) self.assertEqual(test_path.__abspath__, here) + class TestCallerModule(unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.path import caller_module + return caller_module(*arg, **kw) def test_it_level_1(self): from . import test_path + result = self._callFUT(1) self.assertEqual(result, test_path) def test_it_level_2(self): from . import test_path + result = self._callFUT(2) self.assertEqual(result, test_path) def test_it_level_3(self): from . import test_path + result = self._callFUT(3) self.assertNotEqual(result, test_path) def test_it_no___name__(self): class DummyFrame(object): f_globals = {} + class DummySys(object): def _getframe(self, level): return DummyFrame() - modules = {'__main__':'main'} + + modules = {'__main__': 'main'} + dummy_sys = DummySys() result = self._callFUT(3, sys=dummy_sys) self.assertEqual(result, 'main') @@ -72,67 +86,82 @@ class TestCallerModule(unittest.TestCase): class TestCallerPackage(unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.path import caller_package + return caller_package(*arg, **kw) def test_it_level_1(self): import tests + result = self._callFUT(1) self.assertEqual(result, tests) def test_it_level_2(self): import tests + result = self._callFUT(2) self.assertEqual(result, tests) def test_it_level_3(self): import unittest + result = self._callFUT(3) self.assertEqual(result, unittest) def test_it_package(self): import tests + def dummy_caller_module(*arg): return tests + result = self._callFUT(1, caller_module=dummy_caller_module) self.assertEqual(result, tests) - + + class TestPackagePath(unittest.TestCase): def _callFUT(self, package): from pyramid.path import package_path + return package_path(package) def test_it_package(self): import tests + package = DummyPackageOrModule(tests) result = self._callFUT(package) self.assertEqual(result, package.package_path) - + def test_it_module(self): from . import test_path + module = DummyPackageOrModule(test_path) result = self._callFUT(module) self.assertEqual(result, module.package_path) def test_memoization_success(self): from . import test_path + module = DummyPackageOrModule(test_path) self._callFUT(module) self.assertEqual(module.__abspath__, module.package_path) - + def test_memoization_fail(self): from . import test_path + module = DummyPackageOrModule(test_path, raise_exc=TypeError) result = self._callFUT(module) self.assertFalse(hasattr(module, '__abspath__')) self.assertEqual(result, module.package_path) + class TestPackageOf(unittest.TestCase): def _callFUT(self, package): from pyramid.path import package_of + return package_of(package) def test_it_package(self): import tests + package = DummyPackageOrModule(tests) result = self._callFUT(package) self.assertEqual(result, tests) @@ -140,29 +169,35 @@ class TestPackageOf(unittest.TestCase): def test_it_module(self): import tests.test_path import tests + package = DummyPackageOrModule(tests.test_path) result = self._callFUT(package) self.assertEqual(result, tests) + class TestPackageName(unittest.TestCase): def _callFUT(self, package): from pyramid.path import package_name + return package_name(package) def test_it_package(self): import tests + package = DummyPackageOrModule(tests) result = self._callFUT(package) self.assertEqual(result, 'tests') def test_it_namespace_package(self): import tests + package = DummyNamespacePackage(tests) result = self._callFUT(package) self.assertEqual(result, 'tests') - + def test_it_module(self): from . import test_path + module = DummyPackageOrModule(test_path) result = self._callFUT(module) self.assertEqual(result, 'tests') @@ -173,12 +208,15 @@ class TestPackageName(unittest.TestCase): def test_it_main(self): import __main__ + result = self._callFUT(__main__) self.assertEqual(result, '__main__') + class TestResolver(unittest.TestCase): def _getTargetClass(self): from pyramid.path import Resolver + return Resolver def _makeOne(self, package): @@ -187,26 +225,29 @@ class TestResolver(unittest.TestCase): def test_get_package_caller_package(self): import tests from pyramid.path import CALLER_PACKAGE - self.assertEqual(self._makeOne(CALLER_PACKAGE).get_package(), - tests) + + self.assertEqual(self._makeOne(CALLER_PACKAGE).get_package(), tests) def test_get_package_name_caller_package(self): from pyramid.path import CALLER_PACKAGE - self.assertEqual(self._makeOne(CALLER_PACKAGE).get_package_name(), - 'tests') + + self.assertEqual( + self._makeOne(CALLER_PACKAGE).get_package_name(), 'tests' + ) def test_get_package_string(self): import tests - self.assertEqual(self._makeOne('tests').get_package(), - tests) + + self.assertEqual(self._makeOne('tests').get_package(), tests) def test_get_package_name_string(self): - self.assertEqual(self._makeOne('tests').get_package_name(), - 'tests') + self.assertEqual(self._makeOne('tests').get_package_name(), 'tests') + class TestAssetResolver(unittest.TestCase): def _getTargetClass(self): from pyramid.path import AssetResolver + return AssetResolver def _makeOne(self, package='tests'): @@ -214,18 +255,21 @@ class TestAssetResolver(unittest.TestCase): def test_ctor_as_package(self): import sys + tests = sys.modules['tests'] inst = self._makeOne(tests) self.assertEqual(inst.package, tests) def test_ctor_as_str(self): import sys + tests = sys.modules['tests'] inst = self._makeOne('tests') self.assertEqual(inst.package, tests) def test_resolve_abspath(self): from pyramid.path import FSAssetDescriptor + inst = self._makeOne(None) r = inst.resolve(os.path.join(here, 'test_asset.py')) self.assertEqual(r.__class__, FSAssetDescriptor) @@ -233,6 +277,7 @@ class TestAssetResolver(unittest.TestCase): def test_resolve_absspec(self): from pyramid.path import PkgResourcesAssetDescriptor + inst = self._makeOne(None) r = inst.resolve('tests:test_asset.py') self.assertEqual(r.__class__, PkgResourcesAssetDescriptor) @@ -240,6 +285,7 @@ class TestAssetResolver(unittest.TestCase): def test_resolve_relspec_with_pkg(self): from pyramid.path import PkgResourcesAssetDescriptor + inst = self._makeOne('tests') r = inst.resolve('test_asset.py') self.assertEqual(r.__class__, PkgResourcesAssetDescriptor) @@ -252,14 +298,17 @@ class TestAssetResolver(unittest.TestCase): def test_resolve_relspec_caller_package(self): from pyramid.path import PkgResourcesAssetDescriptor from pyramid.path import CALLER_PACKAGE + inst = self._makeOne(CALLER_PACKAGE) r = inst.resolve('test_asset.py') self.assertEqual(r.__class__, PkgResourcesAssetDescriptor) self.assertTrue(r.exists()) - + + class TestPkgResourcesAssetDescriptor(unittest.TestCase): def _getTargetClass(self): from pyramid.path import PkgResourcesAssetDescriptor + return PkgResourcesAssetDescriptor def _makeOne(self, pkg='tests', path='test_asset.py'): @@ -268,11 +317,13 @@ class TestPkgResourcesAssetDescriptor(unittest.TestCase): def test_class_conforms_to_IAssetDescriptor(self): from pyramid.interfaces import IAssetDescriptor from zope.interface.verify import verifyClass + verifyClass(IAssetDescriptor, self._getTargetClass()) - + def test_instance_conforms_to_IAssetDescriptor(self): from pyramid.interfaces import IAssetDescriptor from zope.interface.verify import verifyObject + verifyObject(IAssetDescriptor, self._makeOne()) def test_absspec(self): @@ -288,33 +339,31 @@ class TestPkgResourcesAssetDescriptor(unittest.TestCase): inst.pkg_resources = DummyPkgResource() inst.pkg_resources.resource_stream = lambda x, y: '%s:%s' % (x, y) s = inst.stream() - self.assertEqual(s, - '%s:%s' % ('tests', 'test_asset.py')) + self.assertEqual(s, '%s:%s' % ('tests', 'test_asset.py')) def test_isdir(self): inst = self._makeOne() inst.pkg_resources = DummyPkgResource() inst.pkg_resources.resource_isdir = lambda x, y: '%s:%s' % (x, y) - self.assertEqual(inst.isdir(), - '%s:%s' % ('tests', 'test_asset.py')) + self.assertEqual(inst.isdir(), '%s:%s' % ('tests', 'test_asset.py')) def test_listdir(self): inst = self._makeOne() inst.pkg_resources = DummyPkgResource() inst.pkg_resources.resource_listdir = lambda x, y: '%s:%s' % (x, y) - self.assertEqual(inst.listdir(), - '%s:%s' % ('tests', 'test_asset.py')) + self.assertEqual(inst.listdir(), '%s:%s' % ('tests', 'test_asset.py')) def test_exists(self): inst = self._makeOne() inst.pkg_resources = DummyPkgResource() inst.pkg_resources.resource_exists = lambda x, y: '%s:%s' % (x, y) - self.assertEqual(inst.exists(), - '%s:%s' % ('tests', 'test_asset.py')) + self.assertEqual(inst.exists(), '%s:%s' % ('tests', 'test_asset.py')) + class TestFSAssetDescriptor(unittest.TestCase): def _getTargetClass(self): from pyramid.path import FSAssetDescriptor + return FSAssetDescriptor def _makeOne(self, path=os.path.join(here, 'test_asset.py')): @@ -323,11 +372,13 @@ class TestFSAssetDescriptor(unittest.TestCase): def test_class_conforms_to_IAssetDescriptor(self): from pyramid.interfaces import IAssetDescriptor from zope.interface.verify import verifyClass + verifyClass(IAssetDescriptor, self._getTargetClass()) - + def test_instance_conforms_to_IAssetDescriptor(self): from pyramid.interfaces import IAssetDescriptor from zope.interface.verify import verifyObject + verifyObject(IAssetDescriptor, self._makeOne()) def test_absspec(self): @@ -361,9 +412,11 @@ class TestFSAssetDescriptor(unittest.TestCase): inst = self._makeOne() self.assertTrue(inst.exists()) + class TestDottedNameResolver(unittest.TestCase): def _makeOne(self, package=None): from pyramid.path import DottedNameResolver + return DottedNameResolver(package) def config_exc(self, func, *arg, **kw): @@ -372,7 +425,7 @@ class TestDottedNameResolver(unittest.TestCase): except ValueError as e: return e else: - raise AssertionError('Invalid not raised') # pragma: no cover + raise AssertionError('Invalid not raised') # pragma: no cover def test_zope_dottedname_style_resolve_builtin(self): typ = self._makeOne() @@ -385,30 +438,40 @@ class TestDottedNameResolver(unittest.TestCase): def test_zope_dottedname_style_resolve_absolute(self): typ = self._makeOne() result = typ._zope_dottedname_style( - 'tests.test_path.TestDottedNameResolver', None) + 'tests.test_path.TestDottedNameResolver', None + ) self.assertEqual(result, self.__class__) def test_zope_dottedname_style_irrresolveable_absolute(self): typ = self._makeOne() - self.assertRaises(ImportError, typ._zope_dottedname_style, - 'pyramid.test_path.nonexisting_name', None) + self.assertRaises( + ImportError, + typ._zope_dottedname_style, + 'pyramid.test_path.nonexisting_name', + None, + ) def test__zope_dottedname_style_resolve_relative(self): import tests + typ = self._makeOne() result = typ._zope_dottedname_style( - '.test_path.TestDottedNameResolver', tests) + '.test_path.TestDottedNameResolver', tests + ) self.assertEqual(result, self.__class__) def test__zope_dottedname_style_resolve_relative_leading_dots(self): import tests.test_path + typ = self._makeOne() result = typ._zope_dottedname_style( - '..tests.test_path.TestDottedNameResolver', tests) + '..tests.test_path.TestDottedNameResolver', tests + ) self.assertEqual(result, self.__class__) def test__zope_dottedname_style_resolve_relative_is_dot(self): import tests + typ = self._makeOne() result = typ._zope_dottedname_style('.', tests) self.assertEqual(result, tests) @@ -417,24 +480,28 @@ class TestDottedNameResolver(unittest.TestCase): typ = self._makeOne() e = self.config_exc(typ._zope_dottedname_style, '.', None) self.assertEqual( - e.args[0], - "relative name '.' irresolveable without package") + e.args[0], "relative name '.' irresolveable without package" + ) def test_zope_dottedname_style_resolve_relative_nocurrentpackage(self): typ = self._makeOne() e = self.config_exc(typ._zope_dottedname_style, '.whatever', None) self.assertEqual( e.args[0], - "relative name '.whatever' irresolveable without package") + "relative name '.whatever' irresolveable without package", + ) def test_zope_dottedname_style_irrresolveable_relative(self): import tests + typ = self._makeOne() - self.assertRaises(ImportError, typ._zope_dottedname_style, - '.notexisting', tests) + self.assertRaises( + ImportError, typ._zope_dottedname_style, '.notexisting', tests + ) def test__zope_dottedname_style_resolveable_relative(self): import tests + typ = self._makeOne() result = typ._zope_dottedname_style('.', tests) self.assertEqual(result, tests) @@ -442,49 +509,58 @@ class TestDottedNameResolver(unittest.TestCase): def test__zope_dottedname_style_irresolveable_absolute(self): typ = self._makeOne() self.assertRaises( - ImportError, - typ._zope_dottedname_style, 'pyramid.fudge.bar', None) + ImportError, typ._zope_dottedname_style, 'pyramid.fudge.bar', None + ) def test__zope_dottedname_style_resolveable_absolute(self): typ = self._makeOne() result = typ._zope_dottedname_style( - 'tests.test_path.TestDottedNameResolver', None) + 'tests.test_path.TestDottedNameResolver', None + ) self.assertEqual(result, self.__class__) def test__pkg_resources_style_resolve_absolute(self): typ = self._makeOne() result = typ._pkg_resources_style( - 'tests.test_path:TestDottedNameResolver', None) + 'tests.test_path:TestDottedNameResolver', None + ) self.assertEqual(result, self.__class__) def test__pkg_resources_style_irrresolveable_absolute(self): typ = self._makeOne() - self.assertRaises(ImportError, typ._pkg_resources_style, - 'tests:nonexisting', None) + self.assertRaises( + ImportError, typ._pkg_resources_style, 'tests:nonexisting', None + ) def test__pkg_resources_style_resolve_relative(self): import tests + typ = self._makeOne() result = typ._pkg_resources_style( - '.test_path:TestDottedNameResolver', tests) + '.test_path:TestDottedNameResolver', tests + ) self.assertEqual(result, self.__class__) def test__pkg_resources_style_resolve_relative_is_dot(self): import tests + typ = self._makeOne() result = typ._pkg_resources_style('.', tests) self.assertEqual(result, tests) def test__pkg_resources_style_resolve_relative_nocurrentpackage(self): typ = self._makeOne() - self.assertRaises(ValueError, typ._pkg_resources_style, - '.whatever', None) + self.assertRaises( + ValueError, typ._pkg_resources_style, '.whatever', None + ) def test__pkg_resources_style_irrresolveable_relative(self): import pyramid + typ = self._makeOne() - self.assertRaises(ImportError, typ._pkg_resources_style, - ':notexisting', pyramid) + self.assertRaises( + ImportError, typ._pkg_resources_style, ':notexisting', pyramid + ) def test_resolve_not_a_string(self): typ = self._makeOne() @@ -493,14 +569,12 @@ class TestDottedNameResolver(unittest.TestCase): def test_resolve_using_pkgresources_style(self): typ = self._makeOne() - result = typ.resolve( - 'tests.test_path:TestDottedNameResolver') + result = typ.resolve('tests.test_path:TestDottedNameResolver') self.assertEqual(result, self.__class__) def test_resolve_using_zope_dottedname_style(self): typ = self._makeOne() - result = typ.resolve( - 'tests.test_path:TestDottedNameResolver') + result = typ.resolve('tests.test_path:TestDottedNameResolver') self.assertEqual(result, self.__class__) def test_resolve_missing_raises(self): @@ -509,23 +583,30 @@ class TestDottedNameResolver(unittest.TestCase): def test_resolve_caller_package(self): from pyramid.path import CALLER_PACKAGE + typ = self._makeOne(CALLER_PACKAGE) - self.assertEqual(typ.resolve('.test_path.TestDottedNameResolver'), - self.__class__) + self.assertEqual( + typ.resolve('.test_path.TestDottedNameResolver'), self.__class__ + ) def test_maybe_resolve_caller_package(self): from pyramid.path import CALLER_PACKAGE + typ = self._makeOne(CALLER_PACKAGE) - self.assertEqual(typ.maybe_resolve('.test_path.TestDottedNameResolver'), - self.__class__) + self.assertEqual( + typ.maybe_resolve('.test_path.TestDottedNameResolver'), + self.__class__, + ) def test_ctor_string_module_resolveable(self): import tests + typ = self._makeOne('tests.test_path') self.assertEqual(typ.package, tests) def test_ctor_string_package_resolveable(self): import tests + typ = self._makeOne('tests') self.assertEqual(typ.package, tests) @@ -535,11 +616,13 @@ class TestDottedNameResolver(unittest.TestCase): def test_ctor_module(self): import tests from . import test_path + typ = self._makeOne(test_path) self.assertEqual(typ.package, tests) def test_ctor_package(self): import tests + typ = self._makeOne(tests) self.assertEqual(typ.package, tests) @@ -547,16 +630,20 @@ class TestDottedNameResolver(unittest.TestCase): typ = self._makeOne(None) self.assertEqual(typ.package, None) + class DummyPkgResource(object): pass + class DummyPackageOrModule: def __init__(self, real_package_or_module, raise_exc=None): self.__dict__['raise_exc'] = raise_exc self.__dict__['__name__'] = real_package_or_module.__name__ import os + self.__dict__['package_path'] = os.path.dirname( - os.path.abspath(real_package_or_module.__file__)) + os.path.abspath(real_package_or_module.__file__) + ) self.__dict__['__file__'] = real_package_or_module.__file__ def __setattr__(self, key, val): @@ -564,12 +651,15 @@ class DummyPackageOrModule: raise self.raise_exc self.__dict__[key] = val + class DummyNamespacePackage: """Has no __file__ attribute. """ - + def __init__(self, real_package_or_module): self.__name__ = real_package_or_module.__name__ import os + self.package_path = os.path.dirname( - os.path.abspath(real_package_or_module.__file__)) + os.path.abspath(real_package_or_module.__file__) + ) diff --git a/tests/test_predicates.py b/tests/test_predicates.py index da0b44708..c072b4229 100644 --- a/tests/test_predicates.py +++ b/tests/test_predicates.py @@ -4,18 +4,20 @@ from pyramid import testing from pyramid.compat import text_ + class TestXHRPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import XHRPredicate + return XHRPredicate(val, None) - + def test___call___true(self): inst = self._makeOne(True) request = Dummy() request.is_xhr = True result = inst(None, request) self.assertTrue(result) - + def test___call___false(self): inst = self._makeOne(True) request = Dummy() @@ -31,60 +33,65 @@ class TestXHRPredicate(unittest.TestCase): inst = self._makeOne(True) self.assertEqual(inst.phash(), 'xhr = True') + class TestRequestMethodPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import RequestMethodPredicate + return RequestMethodPredicate(val, None) def test_ctor_get_but_no_head(self): inst = self._makeOne('GET') self.assertEqual(inst.val, ('GET', 'HEAD')) - + def test___call___true_single(self): inst = self._makeOne('GET') request = Dummy() request.method = 'GET' result = inst(None, request) self.assertTrue(result) - + def test___call___true_multi(self): - inst = self._makeOne(('GET','HEAD')) + inst = self._makeOne(('GET', 'HEAD')) request = Dummy() request.method = 'GET' result = inst(None, request) self.assertTrue(result) def test___call___false(self): - inst = self._makeOne(('GET','HEAD')) + inst = self._makeOne(('GET', 'HEAD')) request = Dummy() request.method = 'POST' result = inst(None, request) self.assertFalse(result) def test_text(self): - inst = self._makeOne(('HEAD','GET')) + inst = self._makeOne(('HEAD', 'GET')) self.assertEqual(inst.text(), 'request_method = GET,HEAD') def test_phash(self): - inst = self._makeOne(('HEAD','GET')) + inst = self._makeOne(('HEAD', 'GET')) self.assertEqual(inst.phash(), 'request_method = GET,HEAD') + class TestPathInfoPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import PathInfoPredicate + return PathInfoPredicate(val, None) def test_ctor_compilefail(self): from pyramid.exceptions import ConfigurationError + self.assertRaises(ConfigurationError, self._makeOne, '\\') - + def test___call___true(self): inst = self._makeOne(r'/\d{2}') request = Dummy() request.upath_info = text_('/12') result = inst(None, request) self.assertTrue(result) - + def test___call___false(self): inst = self._makeOne(r'/\d{2}') request = Dummy() @@ -100,36 +107,38 @@ class TestPathInfoPredicate(unittest.TestCase): inst = self._makeOne('/') self.assertEqual(inst.phash(), 'path_info = /') + class TestRequestParamPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import RequestParamPredicate + return RequestParamPredicate(val, None) def test___call___true_exists(self): inst = self._makeOne('abc') request = Dummy() - request.params = {'abc':1} + request.params = {'abc': 1} result = inst(None, request) self.assertTrue(result) def test___call___true_withval(self): inst = self._makeOne('abc=1') request = Dummy() - request.params = {'abc':'1'} + request.params = {'abc': '1'} result = inst(None, request) self.assertTrue(result) def test___call___true_multi(self): inst = self._makeOne(('abc', '=def =2= ')) request = Dummy() - request.params = {'abc':'1', '=def': '2='} + request.params = {'abc': '1', '=def': '2='} result = inst(None, request) self.assertTrue(result) def test___call___false_multi(self): inst = self._makeOne(('abc=3', 'def =2 ')) request = Dummy() - request.params = {'abc':'3', 'def': '1'} + request.params = {'abc': '3', 'def': '1'} result = inst(None, request) self.assertFalse(result) @@ -172,26 +181,27 @@ class TestRequestParamPredicate(unittest.TestCase): inst = self._makeOne('abc= 1') self.assertEqual(inst.phash(), "request_param abc=1") + class TestMatchParamPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import MatchParamPredicate + return MatchParamPredicate(val, None) def test___call___true_single(self): inst = self._makeOne('abc=1') request = Dummy() - request.matchdict = {'abc':'1'} + request.matchdict = {'abc': '1'} result = inst(None, request) self.assertTrue(result) - def test___call___true_multi(self): inst = self._makeOne(('abc=1', 'def=2')) request = Dummy() - request.matchdict = {'abc':'1', 'def':'2'} + request.matchdict = {'abc': '1', 'def': '2'} result = inst(None, request) self.assertTrue(result) - + def test___call___false(self): inst = self._makeOne('abc=1') request = Dummy() @@ -214,9 +224,11 @@ class TestMatchParamPredicate(unittest.TestCase): inst = self._makeOne(('def= 1', 'abc =2')) self.assertEqual(inst.phash(), 'match_param abc=2,def=1') + class TestCustomPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import CustomPredicate + return CustomPredicate(val, None) def test___call___true(self): @@ -224,15 +236,17 @@ class TestCustomPredicate(unittest.TestCase): self.assertEqual(context, None) self.assertEqual(request, None) return True + inst = self._makeOne(func) result = inst(None, None) self.assertTrue(result) - + def test___call___false(self): def func(context, request): self.assertEqual(context, None) self.assertEqual(request, None) return False + inst = self._makeOne(func) result = inst(None, None) self.assertFalse(result) @@ -242,7 +256,7 @@ class TestCustomPredicate(unittest.TestCase): pred.__text__ = 'text' inst = self._makeOne(pred) self.assertEqual(inst.text(), 'text') - + def test_text_func_repr(self): pred = predicate() inst = self._makeOne(pred) @@ -253,39 +267,44 @@ class TestCustomPredicate(unittest.TestCase): inst = self._makeOne(pred) self.assertEqual(inst.phash(), 'custom:1') + class TestTraversePredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import TraversePredicate + return TraversePredicate(val, None) - + def test___call__traverse_has_remainder_already(self): inst = self._makeOne('/1/:a/:b') - info = {'traverse':'abc'} + info = {'traverse': 'abc'} request = Dummy() result = inst(info, request) self.assertEqual(result, True) - self.assertEqual(info, {'traverse':'abc'}) + self.assertEqual(info, {'traverse': 'abc'}) def test___call__traverse_matches(self): inst = self._makeOne('/1/:a/:b') - info = {'match':{'a':'a', 'b':'b'}} + info = {'match': {'a': 'a', 'b': 'b'}} request = Dummy() result = inst(info, request) self.assertEqual(result, True) - self.assertEqual(info, {'match': - {'a':'a', 'b':'b', 'traverse':('1', 'a', 'b')}}) + self.assertEqual( + info, {'match': {'a': 'a', 'b': 'b', 'traverse': ('1', 'a', 'b')}} + ) def test___call__traverse_matches_with_highorder_chars(self): inst = self._makeOne(text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8')) - info = {'match':{'x':text_(b'Qu\xc3\xa9bec', 'utf-8')}} + info = {'match': {'x': text_(b'Qu\xc3\xa9bec', 'utf-8')}} request = Dummy() result = inst(info, request) self.assertEqual(result, True) self.assertEqual( info['match']['traverse'], - (text_(b'La Pe\xc3\xb1a', 'utf-8'), - text_(b'Qu\xc3\xa9bec', 'utf-8')) - ) + ( + text_(b'La Pe\xc3\xb1a', 'utf-8'), + text_(b'Qu\xc3\xa9bec', 'utf-8'), + ), + ) def test_text(self): inst = self._makeOne('/abc') @@ -295,9 +314,11 @@ class TestTraversePredicate(unittest.TestCase): inst = self._makeOne('/abc') self.assertEqual(inst.phash(), '') + class Test_CheckCSRFTokenPredicate(unittest.TestCase): def _makeOne(self, val, config): from pyramid.predicates import CheckCSRFTokenPredicate + return CheckCSRFTokenPredicate(val, config) def test_text(self): @@ -307,28 +328,32 @@ class Test_CheckCSRFTokenPredicate(unittest.TestCase): def test_phash(self): inst = self._makeOne(True, None) self.assertEqual(inst.phash(), 'check_csrf = True') - + def test_it_call_val_True(self): inst = self._makeOne(True, None) request = Dummy() + def check_csrf_token(req, val, raises=True): self.assertEqual(req, request) self.assertEqual(val, 'csrf_token') self.assertEqual(raises, False) return True - inst.check_csrf_token = check_csrf_token + + inst.check_csrf_token = check_csrf_token result = inst(None, request) self.assertEqual(result, True) def test_it_call_val_str(self): inst = self._makeOne('abc', None) request = Dummy() + def check_csrf_token(req, val, raises=True): self.assertEqual(req, request) self.assertEqual(val, 'abc') self.assertEqual(raises, False) return True - inst.check_csrf_token = check_csrf_token + + inst.check_csrf_token = check_csrf_token result = inst(None, request) self.assertEqual(result, True) @@ -338,36 +363,38 @@ class Test_CheckCSRFTokenPredicate(unittest.TestCase): result = inst(None, request) self.assertEqual(result, True) + class TestHeaderPredicate(unittest.TestCase): def _makeOne(self, val): from pyramid.predicates import HeaderPredicate + return HeaderPredicate(val, None) def test___call___true_exists(self): inst = self._makeOne('abc') request = Dummy() - request.headers = {'abc':1} + request.headers = {'abc': 1} result = inst(None, request) self.assertTrue(result) def test___call___true_withval(self): inst = self._makeOne('abc:1') request = Dummy() - request.headers = {'abc':'1'} + request.headers = {'abc': '1'} result = inst(None, request) self.assertTrue(result) def test___call___true_withregex(self): inst = self._makeOne(r'abc:\d+') request = Dummy() - request.headers = {'abc':'1'} + request.headers = {'abc': '1'} result = inst(None, request) self.assertTrue(result) def test___call___false_withregex(self): inst = self._makeOne(r'abc:\d+') request = Dummy() - request.headers = {'abc':'a'} + request.headers = {'abc': 'a'} result = inst(None, request) self.assertFalse(result) @@ -402,9 +429,11 @@ class TestHeaderPredicate(unittest.TestCase): inst = self._makeOne(r'abc:\d+') self.assertEqual(inst.phash(), r'header abc=\d+') + class Test_PhysicalPathPredicate(unittest.TestCase): def _makeOne(self, val, config): from pyramid.predicates import PhysicalPathPredicate + return PhysicalPathPredicate(val, config) def test_text(self): @@ -414,7 +443,7 @@ class Test_PhysicalPathPredicate(unittest.TestCase): def test_phash(self): inst = self._makeOne('/', None) self.assertEqual(inst.phash(), "physical_path = ('',)") - + def test_it_call_val_tuple_True(self): inst = self._makeOne(('', 'abc'), None) root = Dummy() @@ -460,31 +489,34 @@ class Test_PhysicalPathPredicate(unittest.TestCase): context = Dummy() self.assertFalse(inst(context, None)) + class Test_EffectivePrincipalsPredicate(unittest.TestCase): def setUp(self): self.config = testing.setUp() def tearDown(self): testing.tearDown() - + def _makeOne(self, val, config): from pyramid.predicates import EffectivePrincipalsPredicate + return EffectivePrincipalsPredicate(val, config) def test_text(self): inst = self._makeOne(('verna', 'fred'), None) - self.assertEqual(inst.text(), - "effective_principals = ['fred', 'verna']") + self.assertEqual( + inst.text(), "effective_principals = ['fred', 'verna']" + ) def test_text_noniter(self): inst = self._makeOne('verna', None) - self.assertEqual(inst.text(), - "effective_principals = ['verna']") + self.assertEqual(inst.text(), "effective_principals = ['verna']") def test_phash(self): inst = self._makeOne(('verna', 'fred'), None) - self.assertEqual(inst.phash(), - "effective_principals = ['fred', 'verna']") + self.assertEqual( + inst.phash(), "effective_principals = ['fred', 'verna']" + ) def test_it_call_no_authentication_policy(self): request = testing.DummyRequest() @@ -501,6 +533,7 @@ class Test_EffectivePrincipalsPredicate(unittest.TestCase): def test_it_call_authentication_policy_provides_superset_implicit(self): from pyramid.security import Authenticated + request = testing.DummyRequest() self.config.testing_securitypolicy('fred', groupids=('verna', 'bambi')) inst = self._makeOne(Authenticated, None) @@ -518,6 +551,7 @@ class Test_EffectivePrincipalsPredicate(unittest.TestCase): class TestNotted(unittest.TestCase): def _makeOne(self, predicate): from pyramid.predicates import Notted + return Notted(predicate) def test_it_with_phash_val(self): @@ -534,15 +568,19 @@ class TestNotted(unittest.TestCase): self.assertEqual(inst.phash(), '') self.assertEqual(inst(None, None), True) + class predicate(object): def __repr__(self): return 'predicate' + def __hash__(self): return 1 + class Dummy(object): pass + class DummyPredicate(object): def __init__(self, result): self.result = result diff --git a/tests/test_registry.py b/tests/test_registry.py index a07c7660d..f35a54dba 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -1,10 +1,12 @@ import unittest + class TestRegistry(unittest.TestCase): def _getTargetClass(self): from pyramid.registry import Registry + return Registry - + def _makeOne(self, *args, **kw): return self._getTargetClass()(*args, **kw) @@ -35,8 +37,10 @@ class TestRegistry(unittest.TestCase): registry = self._makeOne() self.assertEqual(registry.has_listeners, False) L = [] + def f(event): L.append(event) + registry.registerHandler(f, [IDummyEvent]) self.assertEqual(registry.has_listeners, True) event = DummyEvent() @@ -47,8 +51,10 @@ class TestRegistry(unittest.TestCase): registry = self._makeOne() self.assertEqual(registry.has_listeners, False) from zope.interface import Interface - registry.registerSubscriptionAdapter(DummyEvent, - [IDummyEvent], Interface) + + registry.registerSubscriptionAdapter( + DummyEvent, [IDummyEvent], Interface + ) self.assertEqual(registry.has_listeners, True) def test__get_settings(self): @@ -64,6 +70,7 @@ class TestRegistry(unittest.TestCase): def test_init_forwards_args(self): from zope.interface import Interface from zope.interface.registry import Components + dummy = object() c = Components() c.registerUtility(dummy, Interface) @@ -74,17 +81,20 @@ class TestRegistry(unittest.TestCase): def test_init_forwards_kw(self): from zope.interface import Interface from zope.interface.registry import Components + dummy = object() c = Components() c.registerUtility(dummy, Interface) registry = self._makeOne(bases=(c,)) self.assertEqual(registry.getUtility(Interface), dummy) + class TestIntrospector(unittest.TestCase): def _getTargetClass(slf): from pyramid.registry import Introspector + return Introspector - + def _makeOne(self): return self._getTargetClass()() @@ -92,6 +102,7 @@ class TestIntrospector(unittest.TestCase): from zope.interface.verify import verifyClass from zope.interface.verify import verifyObject from pyramid.interfaces import IIntrospector + verifyClass(IIntrospector, self._getTargetClass()) verifyObject(IIntrospector, self._makeOne()) @@ -100,8 +111,8 @@ class TestIntrospector(unittest.TestCase): intr = DummyIntrospectable() inst.add(intr) self.assertEqual(intr.order, 0) - category = {'discriminator':intr, 'discriminator_hash':intr} - self.assertEqual(inst._categories, {'category':category}) + category = {'discriminator': intr, 'discriminator_hash': intr} + self.assertEqual(inst._categories, {'category': category}) def test_get_success(self): inst = self._makeOne() @@ -130,9 +141,9 @@ class TestIntrospector(unittest.TestCase): inst.add(intr2) inst.add(intr) expected = [ - {'introspectable':intr2, 'related':[]}, - {'introspectable':intr, 'related':[]}, - ] + {'introspectable': intr2, 'related': []}, + {'introspectable': intr, 'related': []}, + ] self.assertEqual(inst.get_category('category'), expected) def test_get_category_returns_default_on_miss(self): @@ -141,6 +152,7 @@ class TestIntrospector(unittest.TestCase): def test_get_category_with_sortkey(self): import operator + inst = self._makeOne() intr = DummyIntrospectable() intr.foo = 2 @@ -151,15 +163,17 @@ class TestIntrospector(unittest.TestCase): inst.add(intr) inst.add(intr2) expected = [ - {'introspectable':intr2, 'related':[]}, - {'introspectable':intr, 'related':[]}, - ] + {'introspectable': intr2, 'related': []}, + {'introspectable': intr, 'related': []}, + ] self.assertEqual( inst.get_category('category', sort_key=operator.attrgetter('foo')), - expected) + expected, + ) def test_categorized(self): import operator + inst = self._makeOne() intr = DummyIntrospectable() intr.foo = 2 @@ -169,12 +183,18 @@ class TestIntrospector(unittest.TestCase): intr2.foo = 1 inst.add(intr) inst.add(intr2) - expected = [('category', [ - {'introspectable':intr2, 'related':[]}, - {'introspectable':intr, 'related':[]}, - ])] + expected = [ + ( + 'category', + [ + {'introspectable': intr2, 'related': []}, + {'introspectable': intr, 'related': []}, + ], + ) + ] self.assertEqual( - inst.categorized(sort_key=operator.attrgetter('foo')), expected) + inst.categorized(sort_key=operator.attrgetter('foo')), expected + ) def test_categories(self): inst = self._makeOne() @@ -191,16 +211,20 @@ class TestIntrospector(unittest.TestCase): intr2.discriminator_hash = 'discriminator2_hash' inst.add(intr) inst.add(intr2) - inst.relate(('category', 'discriminator'), - ('category2', 'discriminator2')) + inst.relate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) inst.remove('category', 'discriminator') - self.assertEqual(inst._categories, - {'category': - {}, - 'category2': - {'discriminator2': intr2, - 'discriminator2_hash': intr2} - }) + self.assertEqual( + inst._categories, + { + 'category': {}, + 'category2': { + 'discriminator2': intr2, + 'discriminator2_hash': intr2, + }, + }, + ) self.assertEqual(inst._refs.get(intr), None) self.assertEqual(inst._refs[intr2], []) @@ -217,16 +241,22 @@ class TestIntrospector(unittest.TestCase): intr2.discriminator_hash = 'discriminator2_hash' inst.add(intr) inst.add(intr2) - inst.relate(('category', 'discriminator'), - ('category2', 'discriminator2')) - self.assertEqual(inst._categories, - {'category': - {'discriminator':intr, - 'discriminator_hash':intr}, - 'category2': - {'discriminator2': intr2, - 'discriminator2_hash': intr2} - }) + inst.relate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) + self.assertEqual( + inst._categories, + { + 'category': { + 'discriminator': intr, + 'discriminator_hash': intr, + }, + 'category2': { + 'discriminator2': intr2, + 'discriminator2_hash': intr2, + }, + }, + ) self.assertEqual(inst._refs[intr], [intr2]) self.assertEqual(inst._refs[intr2], [intr]) @@ -238,8 +268,8 @@ class TestIntrospector(unittest.TestCase): KeyError, inst.relate, ('category', 'discriminator'), - ('category2', 'discriminator2') - ) + ('category2', 'discriminator2'), + ) def test_unrelate(self): inst = self._makeOne() @@ -250,18 +280,25 @@ class TestIntrospector(unittest.TestCase): intr2.discriminator_hash = 'discriminator2_hash' inst.add(intr) inst.add(intr2) - inst.relate(('category', 'discriminator'), - ('category2', 'discriminator2')) - inst.unrelate(('category', 'discriminator'), - ('category2', 'discriminator2')) - self.assertEqual(inst._categories, - {'category': - {'discriminator':intr, - 'discriminator_hash':intr}, - 'category2': - {'discriminator2': intr2, - 'discriminator2_hash': intr2} - }) + inst.relate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) + inst.unrelate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) + self.assertEqual( + inst._categories, + { + 'category': { + 'discriminator': intr, + 'discriminator_hash': intr, + }, + 'category2': { + 'discriminator2': intr2, + 'discriminator2_hash': intr2, + }, + }, + ) self.assertEqual(inst._refs[intr], []) self.assertEqual(inst._refs[intr2], []) @@ -274,8 +311,9 @@ class TestIntrospector(unittest.TestCase): intr2.discriminator_hash = 'discriminator2_hash' inst.add(intr) inst.add(intr2) - inst.relate(('category', 'discriminator'), - ('category2', 'discriminator2')) + inst.relate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) self.assertEqual(inst.related(intr), [intr2]) def test_related_fail(self): @@ -287,16 +325,19 @@ class TestIntrospector(unittest.TestCase): intr2.discriminator_hash = 'discriminator2_hash' inst.add(intr) inst.add(intr2) - inst.relate(('category', 'discriminator'), - ('category2', 'discriminator2')) + inst.relate( + ('category', 'discriminator'), ('category2', 'discriminator2') + ) del inst._categories['category'] self.assertRaises(KeyError, inst.related, intr) + class TestIntrospectable(unittest.TestCase): def _getTargetClass(slf): from pyramid.registry import Introspectable + return Introspectable - + def _makeOne(self, *arg, **kw): return self._getTargetClass()(*arg, **kw) @@ -307,6 +348,7 @@ class TestIntrospectable(unittest.TestCase): from zope.interface.verify import verifyClass from zope.interface.verify import verifyObject from pyramid.interfaces import IIntrospectable + verifyClass(IIntrospectable, self._getTargetClass()) verifyObject(IIntrospectable, self._makeOnePopulated()) @@ -326,14 +368,16 @@ class TestIntrospectable(unittest.TestCase): def test___hash__(self): inst = self._makeOnePopulated() - self.assertEqual(hash(inst), - hash((inst.category_name,) + (inst.discriminator,))) + self.assertEqual( + hash(inst), hash((inst.category_name,) + (inst.discriminator,)) + ) def test___repr__(self): inst = self._makeOnePopulated() self.assertEqual( repr(inst), - "<Introspectable category 'category', discriminator 'discrim'>") + "<Introspectable category 'category', discriminator 'discrim'>", + ) def test___nonzero__(self): inst = self._makeOnePopulated() @@ -352,17 +396,22 @@ class TestIntrospectable(unittest.TestCase): inst.register(introspector, action_info) self.assertEqual(inst.action_info, action_info) self.assertEqual(introspector.intrs, [inst]) - self.assertEqual(introspector.relations, - [(('category', 'discrim'), ('category1', 'discrim1'))]) - self.assertEqual(introspector.unrelations, - [(('category', 'discrim'), ('category2', 'discrim2'))]) + self.assertEqual( + introspector.relations, + [(('category', 'discrim'), ('category1', 'discrim1'))], + ) + self.assertEqual( + introspector.unrelations, + [(('category', 'discrim'), ('category2', 'discrim2'))], + ) + class DummyIntrospector(object): def __init__(self): self.intrs = [] self.relations = [] self.unrelations = [] - + def add(self, intr): self.intrs.append(intr) @@ -372,11 +421,13 @@ class DummyIntrospector(object): def unrelate(self, *pairs): self.unrelations.append(pairs) + class DummyModule: __path__ = "foo" __name__ = "dummy" __file__ = '' + class DummyIntrospectable(object): category_name = 'category' discriminator = 'discriminator' @@ -392,10 +443,12 @@ class DummyIntrospectable(object): from zope.interface import Interface from zope.interface import implementer + + class IDummyEvent(Interface): pass + @implementer(IDummyEvent) class DummyEvent(object): pass - diff --git a/tests/test_renderers.py b/tests/test_renderers.py index fce902662..0eacfa996 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -4,6 +4,7 @@ from pyramid.testing import cleanUp from pyramid import testing from pyramid.compat import text_ + class TestJSON(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -13,47 +14,52 @@ class TestJSON(unittest.TestCase): def _makeOne(self, **kw): from pyramid.renderers import JSON + return JSON(**kw) def test_it(self): renderer = self._makeOne()(None) - result = renderer({'a':1}, {}) + result = renderer({'a': 1}, {}) self.assertEqual(result, '{"a": 1}') def test_with_request_content_type_notset(self): request = testing.DummyRequest() renderer = self._makeOne()(None) - renderer({'a':1}, {'request':request}) + renderer({'a': 1}, {'request': request}) self.assertEqual(request.response.content_type, 'application/json') def test_with_request_content_type_set(self): request = testing.DummyRequest() request.response.content_type = 'text/mishmash' renderer = self._makeOne()(None) - renderer({'a':1}, {'request':request}) + renderer({'a': 1}, {'request': request}) self.assertEqual(request.response.content_type, 'text/mishmash') def test_with_custom_adapter(self): request = testing.DummyRequest() from datetime import datetime + def adapter(obj, req): self.assertEqual(req, request) return obj.isoformat() + now = datetime.utcnow() renderer = self._makeOne() renderer.add_adapter(datetime, adapter) - result = renderer(None)({'a':now}, {'request':request}) + result = renderer(None)({'a': now}, {'request': request}) self.assertEqual(result, '{"a": "%s"}' % now.isoformat()) def test_with_custom_adapter2(self): request = testing.DummyRequest() from datetime import datetime + def adapter(obj, req): self.assertEqual(req, request) return obj.isoformat() + now = datetime.utcnow() renderer = self._makeOne(adapters=((datetime, adapter),)) - result = renderer(None)({'a':now}, {'request':request}) + result = renderer(None)({'a': now}, {'request': request}) self.assertEqual(result, '{"a": "%s"}' % now.isoformat()) def test_with_custom_serializer(self): @@ -62,9 +68,10 @@ class TestJSON(unittest.TestCase): self.obj = obj self.kw = kw return 'foo' + serializer = Serializer() renderer = self._makeOne(serializer=serializer, baz=5) - obj = {'a':'b'} + obj = {'a': 'b'} result = renderer(None)(obj, {}) self.assertEqual(result, 'foo') self.assertEqual(serializer.obj, obj) @@ -74,29 +81,34 @@ class TestJSON(unittest.TestCase): def test_with_object_adapter(self): request = testing.DummyRequest() outerself = self + class MyObject(object): def __init__(self, x): self.x = x + def __json__(self, req): outerself.assertEqual(req, request) return {'x': self.x} objects = [MyObject(1), MyObject(2)] renderer = self._makeOne()(None) - result = renderer(objects, {'request':request}) + result = renderer(objects, {'request': request}) self.assertEqual(result, '[{"x": 1}, {"x": 2}]') def test_with_object_adapter_no___json__(self): class MyObject(object): def __init__(self, x): self.x = x + objects = [MyObject(1), MyObject(2)] renderer = self._makeOne()(None) self.assertRaises(TypeError, renderer, objects, {}) + class Test_string_renderer_factory(unittest.TestCase): def _callFUT(self, name): from pyramid.renderers import string_renderer_factory + return string_renderer_factory(name) def test_it_unicode(self): @@ -120,14 +132,14 @@ class Test_string_renderer_factory(unittest.TestCase): def test_with_request_content_type_notset(self): request = testing.DummyRequest() renderer = self._callFUT(None) - renderer('', {'request':request}) + renderer('', {'request': request}) self.assertEqual(request.response.content_type, 'text/plain') def test_with_request_content_type_set(self): request = testing.DummyRequest() request.response.content_type = 'text/mishmash' renderer = self._callFUT(None) - renderer('', {'request':request}) + renderer('', {'request': request}) self.assertEqual(request.response.content_type, 'text/mishmash') @@ -140,46 +152,56 @@ class TestRendererHelper(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.renderers import RendererHelper + return RendererHelper(*arg, **kw) def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IRendererInfo + helper = self._makeOne() verifyObject(IRendererInfo, helper) def test_settings_registry_settings_is_None(self): class Dummy(object): settings = None + helper = self._makeOne(registry=Dummy) self.assertEqual(helper.settings, {}) def test_settings_registry_name_is_None(self): class Dummy(object): settings = None + helper = self._makeOne(registry=Dummy) self.assertEqual(helper.name, None) self.assertEqual(helper.type, '') def test_settings_registry_settings_is_not_None(self): class Dummy(object): - settings = {'a':1} + settings = {'a': 1} + helper = self._makeOne(registry=Dummy) - self.assertEqual(helper.settings, {'a':1}) + self.assertEqual(helper.settings, {'a': 1}) def _registerRendererFactory(self): from pyramid.interfaces import IRendererFactory + def renderer(*arg): def respond(*arg): return arg + renderer.respond = respond return respond - self.config.registry.registerUtility(renderer, IRendererFactory, - name='.foo') + + self.config.registry.registerUtility( + renderer, IRendererFactory, name='.foo' + ) return renderer def _registerResponseFactory(self): from pyramid.interfaces import IResponseFactory + class ResponseFactory(object): pass @@ -192,8 +214,7 @@ class TestRendererHelper(unittest.TestCase): self._registerResponseFactory() request = Dummy() helper = self._makeOne('loo.foo') - response = helper.render_to_response('values', {}, - request=request) + response = helper.render_to_response('values', {}, request=request) self.assertEqual(response.app_iter[0], 'values') self.assertEqual(response.app_iter[1], {}) @@ -204,6 +225,7 @@ class TestRendererHelper(unittest.TestCase): def test_render_view(self): import pyramid.csrf + self._registerRendererFactory() self._registerResponseFactory() request = Dummy() @@ -214,28 +236,35 @@ class TestRendererHelper(unittest.TestCase): response = 'response' response = helper.render_view(request, response, view, context) get_csrf = response.app_iter[1].pop('get_csrf_token') - self.assertEqual(get_csrf.args, (request, )) + self.assertEqual(get_csrf.args, (request,)) self.assertEqual(get_csrf.func, pyramid.csrf.get_csrf_token) self.assertEqual(response.app_iter[0], 'response') - self.assertEqual(response.app_iter[1], - {'renderer_info': helper, - 'renderer_name': 'loo.foo', - 'request': request, - 'context': 'context', - 'view': 'view', - 'req': request,} - ) + self.assertEqual( + response.app_iter[1], + { + 'renderer_info': helper, + 'renderer_name': 'loo.foo', + 'request': request, + 'context': 'context', + 'view': 'view', + 'req': request, + }, + ) def test_render_explicit_registry(self): factory = self._registerRendererFactory() + class DummyRegistry(object): def __init__(self): self.responses = [factory, lambda *arg: {}, None] + def queryUtility(self, iface, name=None): self.queried = True return self.responses.pop(0) + def notify(self, event): self.event = event + reg = DummyRegistry() helper = self._makeOne('loo.foo', registry=reg) result = helper.render('value', {}) @@ -247,6 +276,7 @@ class TestRendererHelper(unittest.TestCase): def test_render_system_values_is_None(self): import pyramid.csrf + self._registerRendererFactory() request = Dummy() context = Dummy() @@ -254,15 +284,16 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') result = helper.render('values', None, request=request) get_csrf = result[1].pop('get_csrf_token') - self.assertEqual(get_csrf.args, (request, )) + self.assertEqual(get_csrf.args, (request,)) self.assertEqual(get_csrf.func, pyramid.csrf.get_csrf_token) - system = {'request':request, - 'context':context, - 'renderer_name':'loo.foo', - 'view':None, - 'renderer_info':helper, - 'req':request, - } + system = { + 'request': request, + 'context': context, + 'renderer_name': 'loo.foo', + 'view': None, + 'renderer_info': helper, + 'req': request, + } self.assertEqual(result[0], 'values') self.assertEqual(result[1], system) @@ -282,6 +313,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_result_is_unicode(self): from pyramid.response import Response + request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') @@ -291,6 +323,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_result_is_str(self): from pyramid.response import Response + request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') @@ -300,6 +333,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_result_is_iterable(self): from pyramid.response import Response + request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') @@ -317,6 +351,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_result_is_None_no_body(self): from pyramid.response import Response + request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') @@ -325,6 +360,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_result_is_None_existing_body_not_molested(self): from pyramid.response import Response + request = testing.DummyRequest() response = Response() response.body = b'abc' @@ -335,9 +371,11 @@ class TestRendererHelper(unittest.TestCase): def test_with_alternate_response_factory(self): from pyramid.interfaces import IResponseFactory + class ResponseFactory(object): def __init__(self): pass + self.config.registry.registerUtility( lambda r: ResponseFactory(), IResponseFactory ) @@ -350,6 +388,7 @@ class TestRendererHelper(unittest.TestCase): def test__make_response_with_real_request(self): # functional from pyramid.request import Request + request = Request({}) request.registry = self.config.registry request.response.status = '406 You Lose' @@ -368,8 +407,9 @@ class TestRendererHelper(unittest.TestCase): def test_clone_allargs(self): helper = self._makeOne('name', 'package', 'registry') - cloned_helper = helper.clone(name='name2', package='package2', - registry='registry2') + cloned_helper = helper.clone( + name='name2', package='package2', registry='registry2' + ) self.assertEqual(cloned_helper.name, 'name2') self.assertEqual(cloned_helper.package, 'package2') self.assertEqual(cloned_helper.registry, 'registry2') @@ -381,12 +421,16 @@ class TestRendererHelper(unittest.TestCase): registry.settings = settings from pyramid.interfaces import IRendererFactory import os + here = os.path.dirname(os.path.abspath(__file__)) fixture = os.path.join(here, 'fixtures/minimal.pt') + def factory(info, **kw): return info + self.config.registry.registerUtility( - factory, IRendererFactory, name='.pt') + factory, IRendererFactory, name='.pt' + ) result = self._makeOne(fixture).renderer self.assertEqual(result.registry, registry) self.assertEqual(result.type, '.pt') @@ -396,17 +440,22 @@ class TestRendererHelper(unittest.TestCase): def test_renderer_with_package(self): import pyramid + registry = self.config.registry settings = {} registry.settings = settings from pyramid.interfaces import IRendererFactory import os + here = os.path.dirname(os.path.abspath(__file__)) fixture = os.path.join(here, 'fixtures/minimal.pt') + def factory(info, **kw): return info + self.config.registry.registerUtility( - factory, IRendererFactory, name='.pt') + factory, IRendererFactory, name='.pt' + ) result = self._makeOne(fixture, pyramid).renderer self.assertEqual(result.registry, registry) self.assertEqual(result.type, '.pt') @@ -418,6 +467,7 @@ class TestRendererHelper(unittest.TestCase): inst = self._makeOne('foo') self.assertRaises(ValueError, getattr, inst, 'renderer') + class TestNullRendererHelper(unittest.TestCase): def setUp(self): self.config = cleanUp() @@ -427,11 +477,13 @@ class TestNullRendererHelper(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.renderers import NullRendererHelper + return NullRendererHelper(*arg, **kw) def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IRendererInfo + helper = self._makeOne() verifyObject(IRendererInfo, helper) @@ -451,6 +503,7 @@ class TestNullRendererHelper(unittest.TestCase): helper = self._makeOne() self.assertTrue(helper.clone() is helper) + class Test_render(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -460,11 +513,11 @@ class Test_render(unittest.TestCase): def _callFUT(self, renderer_name, value, request=None, package=None): from pyramid.renderers import render + return render(renderer_name, value, request=request, package=package) def _registerRenderer(self): - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = self.config.testing_add_renderer('tests:abc/def.pt') renderer.string_response = 'abc' return renderer @@ -478,25 +531,26 @@ class Test_render(unittest.TestCase): def test_it_with_request(self): renderer = self._registerRenderer() request = testing.DummyRequest() - result = self._callFUT('abc/def.pt', - dict(a=1), request=request) + result = self._callFUT('abc/def.pt', dict(a=1), request=request) self.assertEqual(result, 'abc') renderer.assert_(a=1) renderer.assert_(request=request) def test_it_with_package(self): import tests + renderer = self._registerRenderer() request = testing.DummyRequest() - result = self._callFUT('abc/def.pt', dict(a=1), request=request, - package=tests) + result = self._callFUT( + 'abc/def.pt', dict(a=1), request=request, package=tests + ) self.assertEqual(result, 'abc') renderer.assert_(a=1) renderer.assert_(request=request) def test_response_preserved(self): request = testing.DummyRequest() - response = object() # should error if mutated + response = object() # should error if mutated request.response = response # use a json renderer, which will mutate the response result = self._callFUT('json', dict(a=1), request=request) @@ -505,19 +559,23 @@ class Test_render(unittest.TestCase): def test_no_response_to_preserve(self): from pyramid.decorator import reify + class DummyRequestWithClassResponse(object): _response = DummyResponse() _response.content_type = None _response.default_content_type = None + @reify def response(self): return self._response + request = DummyRequestWithClassResponse() # use a json renderer, which will mutate the response result = self._callFUT('json', dict(a=1), request=request) self.assertEqual(result, '{"a": 1}') self.assertFalse('response' in request.__dict__) + class Test_render_to_response(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -525,15 +583,21 @@ class Test_render_to_response(unittest.TestCase): def tearDown(self): testing.tearDown() - def _callFUT(self, renderer_name, value, request=None, package=None, - response=None): + def _callFUT( + self, renderer_name, value, request=None, package=None, response=None + ): from pyramid.renderers import render_to_response - return render_to_response(renderer_name, value, request=request, - package=package, response=response) + + return render_to_response( + renderer_name, + value, + request=request, + package=package, + response=response, + ) def test_it_no_request(self): - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = self.config.testing_add_renderer('tests:abc/def.pt') renderer.string_response = 'abc' response = self._callFUT('abc/def.pt', dict(a=1)) self.assertEqual(response.body, b'abc') @@ -541,31 +605,30 @@ class Test_render_to_response(unittest.TestCase): renderer.assert_(request=None) def test_it_with_request(self): - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = self.config.testing_add_renderer('tests:abc/def.pt') renderer.string_response = 'abc' request = testing.DummyRequest() - response = self._callFUT('abc/def.pt', - dict(a=1), request=request) + response = self._callFUT('abc/def.pt', dict(a=1), request=request) self.assertEqual(response.body, b'abc') renderer.assert_(a=1) renderer.assert_(request=request) def test_it_with_package(self): import tests - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + + renderer = self.config.testing_add_renderer('tests:abc/def.pt') renderer.string_response = 'abc' request = testing.DummyRequest() - response = self._callFUT('abc/def.pt', dict(a=1), request=request, - package=tests) + response = self._callFUT( + 'abc/def.pt', dict(a=1), request=request, package=tests + ) self.assertEqual(response.body, b'abc') renderer.assert_(a=1) renderer.assert_(request=request) def test_response_preserved(self): request = testing.DummyRequest() - response = object() # should error if mutated + response = object() # should error if mutated request.response = response # use a json renderer, which will mutate the response result = self._callFUT('json', dict(a=1), request=request) @@ -575,13 +638,16 @@ class Test_render_to_response(unittest.TestCase): def test_no_response_to_preserve(self): from pyramid.decorator import reify + class DummyRequestWithClassResponse(object): _response = DummyResponse() _response.content_type = None _response.default_content_type = None + @reify def response(self): return self._response + request = DummyRequestWithClassResponse() # use a json renderer, which will mutate the response result = self._callFUT('json', dict(a=1), request=request) @@ -591,15 +657,18 @@ class Test_render_to_response(unittest.TestCase): def test_custom_response_object(self): class DummyRequestWithClassResponse(object): pass + request = DummyRequestWithClassResponse() response = DummyResponse() # use a json renderer, which will mutate the response - result = self._callFUT('json', dict(a=1), request=request, - response=response) + result = self._callFUT( + 'json', dict(a=1), request=request, response=response + ) self.assertTrue(result is response) self.assertEqual(result.body, b'{"a": 1}') self.assertFalse('response' in request.__dict__) + class Test_get_renderer(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -609,38 +678,39 @@ class Test_get_renderer(unittest.TestCase): def _callFUT(self, renderer_name, **kw): from pyramid.renderers import get_renderer + return get_renderer(renderer_name, **kw) def test_it_no_package(self): - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = self.config.testing_add_renderer('tests:abc/def.pt') result = self._callFUT('abc/def.pt') self.assertEqual(result, renderer) def test_it_with_package(self): import tests - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + + renderer = self.config.testing_add_renderer('tests:abc/def.pt') result = self._callFUT('abc/def.pt', package=tests) self.assertEqual(result, renderer) def test_it_with_registry(self): - renderer = self.config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = self.config.testing_add_renderer('tests:abc/def.pt') result = self._callFUT('abc/def.pt', registry=self.config.registry) self.assertEqual(result, renderer) def test_it_with_isolated_registry(self): from pyramid.config import Configurator + isolated_config = Configurator() - renderer = isolated_config.testing_add_renderer( - 'tests:abc/def.pt') + renderer = isolated_config.testing_add_renderer('tests:abc/def.pt') result = self._callFUT('abc/def.pt', registry=isolated_config.registry) self.assertEqual(result, renderer) + class TestJSONP(unittest.TestCase): def _makeOne(self, param_name='callback'): from pyramid.renderers import JSONP + return JSONP(param_name) def test_render_to_jsonp(self): @@ -648,48 +718,53 @@ class TestJSONP(unittest.TestCase): renderer = renderer_factory(None) request = testing.DummyRequest() request.GET['callback'] = 'callback' - result = renderer({'a':'1'}, {'request':request}) + result = renderer({'a': '1'}, {'request': request}) self.assertEqual(result, '/**/callback({"a": "1"});') - self.assertEqual(request.response.content_type, - 'application/javascript') + self.assertEqual( + request.response.content_type, 'application/javascript' + ) def test_render_to_jsonp_with_dot(self): renderer_factory = self._makeOne() renderer = renderer_factory(None) request = testing.DummyRequest() request.GET['callback'] = 'angular.callbacks._0' - result = renderer({'a':'1'}, {'request':request}) + result = renderer({'a': '1'}, {'request': request}) self.assertEqual(result, '/**/angular.callbacks._0({"a": "1"});') - self.assertEqual(request.response.content_type, - 'application/javascript') + self.assertEqual( + request.response.content_type, 'application/javascript' + ) def test_render_to_json(self): renderer_factory = self._makeOne() renderer = renderer_factory(None) request = testing.DummyRequest() - result = renderer({'a':'1'}, {'request':request}) + result = renderer({'a': '1'}, {'request': request}) self.assertEqual(result, '{"a": "1"}') - self.assertEqual(request.response.content_type, - 'application/json') + self.assertEqual(request.response.content_type, 'application/json') def test_render_without_request(self): renderer_factory = self._makeOne() renderer = renderer_factory(None) - result = renderer({'a':'1'}, {}) + result = renderer({'a': '1'}, {}) self.assertEqual(result, '{"a": "1"}') def test_render_to_jsonp_invalid_callback(self): from pyramid.httpexceptions import HTTPBadRequest + renderer_factory = self._makeOne() renderer = renderer_factory(None) request = testing.DummyRequest() request.GET['callback'] = '78mycallback' - self.assertRaises(HTTPBadRequest, renderer, {'a':'1'}, {'request':request}) + self.assertRaises( + HTTPBadRequest, renderer, {'a': '1'}, {'request': request} + ) class Dummy: pass + class DummyResponse: status = '200 OK' default_content_type = 'text/html' @@ -699,7 +774,7 @@ class DummyResponse: body = b'' # compat for renderer that will set unicode on py3 - def _set_text(self, val): # pragma: no cover + def _set_text(self, val): # pragma: no cover self.body = val.encode('utf8') - text = property(fset=_set_text) + text = property(fset=_set_text) diff --git a/tests/test_request.py b/tests/test_request.py index c79c84d63..13e424f79 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -2,16 +2,9 @@ from collections import deque import unittest from pyramid import testing -from pyramid.compat import ( - PY2, - text_, - bytes_, - native_, - ) -from pyramid.security import ( - AuthenticationAPIMixin, - AuthorizationAPIMixin, - ) +from pyramid.compat import PY2, text_, bytes_, native_ +from pyramid.security import AuthenticationAPIMixin, AuthorizationAPIMixin + class TestRequest(unittest.TestCase): def setUp(self): @@ -22,6 +15,7 @@ class TestRequest(unittest.TestCase): def _getTargetClass(self): from pyramid.request import Request + return Request def _makeOne(self, environ=None): @@ -32,26 +26,31 @@ class TestRequest(unittest.TestCase): def _registerResourceURL(self): from pyramid.interfaces import IResourceURL from zope.interface import Interface + class DummyResourceURL(object): def __init__(self, context, request): self.physical_path = '/context/' self.virtual_path = '/context/' + self.config.registry.registerAdapter( - DummyResourceURL, (Interface, Interface), - IResourceURL) + DummyResourceURL, (Interface, Interface), IResourceURL + ) def test_class_conforms_to_IRequest(self): from zope.interface.verify import verifyClass from pyramid.interfaces import IRequest + verifyClass(IRequest, self._getTargetClass()) def test_instance_conforms_to_IRequest(self): from zope.interface.verify import verifyObject from pyramid.interfaces import IRequest + verifyObject(IRequest, self._makeOne()) def test_ResponseClass_is_pyramid_Response(self): from pyramid.response import Response + cls = self._getTargetClass() self.assertEqual(cls.ResponseClass, Response) @@ -61,41 +60,42 @@ class TestRequest(unittest.TestCase): self.assertTrue(isinstance(r, apis)) def test_charset_defaults_to_utf8(self): - r = self._makeOne({'PATH_INFO':'/'}) + r = self._makeOne({'PATH_INFO': '/'}) self.assertEqual(r.charset, 'UTF-8') def test_exception_defaults_to_None(self): - r = self._makeOne({'PATH_INFO':'/'}) + r = self._makeOne({'PATH_INFO': '/'}) self.assertEqual(r.exception, None) def test_matchdict_defaults_to_None(self): - r = self._makeOne({'PATH_INFO':'/'}) + r = self._makeOne({'PATH_INFO': '/'}) self.assertEqual(r.matchdict, None) def test_matched_route_defaults_to_None(self): - r = self._makeOne({'PATH_INFO':'/'}) + r = self._makeOne({'PATH_INFO': '/'}) self.assertEqual(r.matched_route, None) def test_params_decoded_from_utf_8_by_default(self): - environ = { - 'PATH_INFO':'/', - 'QUERY_STRING':'la=La%20Pe%C3%B1a' - } + environ = {'PATH_INFO': '/', 'QUERY_STRING': 'la=La%20Pe%C3%B1a'} request = self._makeOne(environ) request.charset = None self.assertEqual(request.GET['la'], text_(b'La Pe\xf1a')) def test_tmpl_context(self): from pyramid.request import TemplateContext + inst = self._makeOne() result = inst.tmpl_context self.assertEqual(result.__class__, TemplateContext) def test_session_configured(self): from pyramid.interfaces import ISessionFactory + inst = self._makeOne() + def factory(request): return 'orangejuice' + self.config.registry.registerUtility(factory, ISessionFactory) inst.registry = self.config.registry self.assertEqual(inst.session, 'orangejuice') @@ -116,13 +116,15 @@ class TestRequest(unittest.TestCase): inst = self._makeOne(environ) setattr(inst, 'bar', 1) self.assertEqual(getattr(inst, 'bar'), 1) - self.assertEqual(environ, {}) # make sure we're not using adhoc attrs + self.assertEqual(environ, {}) # make sure we're not using adhoc attrs def test_add_response_callback(self): inst = self._makeOne() self.assertEqual(len(inst.response_callbacks), 0) + def callback(request, response): """ """ + inst.add_response_callback(callback) self.assertEqual(list(inst.response_callbacks), [callback]) inst.add_response_callback(callback) @@ -130,12 +132,15 @@ class TestRequest(unittest.TestCase): def test__process_response_callbacks(self): inst = self._makeOne() + def callback1(request, response): request.called1 = True response.called1 = True + def callback2(request, response): - request.called2 = True + request.called2 = True response.called2 = True + inst.add_response_callback(callback1) inst.add_response_callback(callback2) response = DummyResponse() @@ -153,13 +158,16 @@ class TestRequest(unittest.TestCase): See https://github.com/Pylons/pyramid/pull/1373 """ inst = self._makeOne() + def callback1(request, response): request.called1 = True response.called1 = True request.add_response_callback(callback2) + def callback2(request, response): - request.called2 = True + request.called2 = True response.called2 = True + inst.add_response_callback(callback1) response = DummyResponse() inst._process_response_callbacks(response) @@ -172,8 +180,10 @@ class TestRequest(unittest.TestCase): def test_add_finished_callback(self): inst = self._makeOne() self.assertEqual(len(inst.finished_callbacks), 0) + def callback(request): """ """ + inst.add_finished_callback(callback) self.assertEqual(list(inst.finished_callbacks), [callback]) inst.add_finished_callback(callback) @@ -181,10 +191,13 @@ class TestRequest(unittest.TestCase): def test__process_finished_callbacks(self): inst = self._makeOne() + def callback1(request): request.called1 = True + def callback2(request): - request.called2 = True + request.called2 = True + inst.add_finished_callback(callback1) inst.add_finished_callback(callback2) inst._process_finished_callbacks() @@ -195,11 +208,11 @@ class TestRequest(unittest.TestCase): def test_resource_url(self): self._registerResourceURL() environ = { - 'PATH_INFO':'/', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - 'wsgi.url_scheme':'http', - } + 'PATH_INFO': '/', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + 'wsgi.url_scheme': 'http', + } inst = self._makeOne(environ) root = DummyContext() result = inst.resource_url(root) @@ -207,55 +220,74 @@ class TestRequest(unittest.TestCase): def test_route_url(self): environ = { - 'PATH_INFO':'/', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'5432', - 'QUERY_STRING':'la=La%20Pe%C3%B1a', - 'wsgi.url_scheme':'http', - } + 'PATH_INFO': '/', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '5432', + 'QUERY_STRING': 'la=La%20Pe%C3%B1a', + 'wsgi.url_scheme': 'http', + } from pyramid.interfaces import IRoutesMapper + inst = self._makeOne(environ) mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) self.config.registry.registerUtility(mapper, IRoutesMapper) - result = inst.route_url('flub', 'extra1', 'extra2', - a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) - self.assertEqual(result, - 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') + result = inst.route_url( + 'flub', + 'extra1', + 'extra2', + a=1, + b=2, + c=3, + _query={'a': 1}, + _anchor=text_("foo"), + ) + self.assertEqual( + result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo' + ) def test_route_path(self): environ = { - 'PATH_INFO':'/', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'5432', - 'QUERY_STRING':'la=La%20Pe%C3%B1a', - 'wsgi.url_scheme':'http', - } + 'PATH_INFO': '/', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '5432', + 'QUERY_STRING': 'la=La%20Pe%C3%B1a', + 'wsgi.url_scheme': 'http', + } from pyramid.interfaces import IRoutesMapper + inst = self._makeOne(environ) mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) self.config.registry.registerUtility(mapper, IRoutesMapper) - result = inst.route_path('flub', 'extra1', 'extra2', - a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + result = inst.route_path( + 'flub', + 'extra1', + 'extra2', + a=1, + b=2, + c=3, + _query={'a': 1}, + _anchor=text_("foo"), + ) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_static_url(self): from pyramid.interfaces import IStaticURLInfo + environ = { - 'PATH_INFO':'/', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'5432', - 'QUERY_STRING':'', - 'wsgi.url_scheme':'http', - } + 'PATH_INFO': '/', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '5432', + 'QUERY_STRING': '', + 'wsgi.url_scheme': 'http', + } request = self._makeOne(environ) info = DummyStaticURLInfo('abc') self.config.registry.registerUtility(info, IStaticURLInfo) result = request.static_url('pyramid.tests:static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('pyramid.tests:static/foo.css', request, {}) ) + self.assertEqual( + info.args, ('pyramid.tests:static/foo.css', request, {}) + ) def test_is_response_false(self): request = self._makeOne() @@ -264,6 +296,7 @@ class TestRequest(unittest.TestCase): def test_is_response_true_ob_is_pyramid_response(self): from pyramid.response import Response + r = Response('hello') request = self._makeOne() request.registry = self.config.registry @@ -271,62 +304,73 @@ class TestRequest(unittest.TestCase): def test_is_response_false_adapter_is_not_self(self): from pyramid.interfaces import IResponse + request = self._makeOne() request.registry = self.config.registry + def adapter(ob): return object() + class Foo(object): pass + foo = Foo() request.registry.registerAdapter(adapter, (Foo,), IResponse) self.assertEqual(request.is_response(foo), False) - + def test_is_response_adapter_true(self): from pyramid.interfaces import IResponse + request = self._makeOne() request.registry = self.config.registry + class Foo(object): pass + foo = Foo() + def adapter(ob): return ob + request.registry.registerAdapter(adapter, (Foo,), IResponse) self.assertEqual(request.is_response(foo), True) def test_json_body_invalid_json(self): - request = self._makeOne({'REQUEST_METHOD':'POST'}) + request = self._makeOne({'REQUEST_METHOD': 'POST'}) request.body = b'{' self.assertRaises(ValueError, getattr, request, 'json_body') - + def test_json_body_valid_json(self): - request = self._makeOne({'REQUEST_METHOD':'POST'}) + request = self._makeOne({'REQUEST_METHOD': 'POST'}) request.body = b'{"a":1}' - self.assertEqual(request.json_body, {'a':1}) + self.assertEqual(request.json_body, {'a': 1}) def test_json_body_alternate_charset(self): import json - request = self._makeOne({'REQUEST_METHOD':'POST'}) + + request = self._makeOne({'REQUEST_METHOD': 'POST'}) inp = text_( - b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', - 'utf-8' - ) + b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8' + ) if PY2: - body = json.dumps({'a':inp}).decode('utf-8').encode('utf-16') + body = json.dumps({'a': inp}).decode('utf-8').encode('utf-16') else: - body = bytes(json.dumps({'a':inp}), 'utf-16') + body = bytes(json.dumps({'a': inp}), 'utf-16') request.body = body request.content_type = 'application/json; charset=utf-16' - self.assertEqual(request.json_body, {'a':inp}) + self.assertEqual(request.json_body, {'a': inp}) def test_json_body_GET_request(self): - request = self._makeOne({'REQUEST_METHOD':'GET'}) + request = self._makeOne({'REQUEST_METHOD': 'GET'}) self.assertRaises(ValueError, getattr, request, 'json_body') def test_set_property(self): request = self._makeOne() opts = [2, 1] + def connect(obj): return opts.pop() + request.set_property(connect, name='db') self.assertEqual(1, request.db) self.assertEqual(2, request.db) @@ -334,35 +378,43 @@ class TestRequest(unittest.TestCase): def test_set_property_reify(self): request = self._makeOne() opts = [2, 1] + def connect(obj): return opts.pop() + request.set_property(connect, name='db', reify=True) self.assertEqual(1, request.db) self.assertEqual(1, request.db) + class Test_route_request_iface(unittest.TestCase): def _callFUT(self, name): from pyramid.request import route_request_iface + return route_request_iface(name) def test_it(self): iface = self._callFUT('routename') self.assertEqual(iface.__name__, 'routename_IRequest') self.assertTrue(hasattr(iface, 'combined')) - self.assertEqual(iface.combined.__name__, 'routename_combined_IRequest') + self.assertEqual( + iface.combined.__name__, 'routename_combined_IRequest' + ) def test_it_routename_with_spaces(self): # see https://github.com/Pylons/pyramid/issues/232 iface = self._callFUT('routename with spaces') self.assertEqual(iface.__name__, 'routename with spaces_IRequest') self.assertTrue(hasattr(iface, 'combined')) - self.assertEqual(iface.combined.__name__, - 'routename with spaces_combined_IRequest') - + self.assertEqual( + iface.combined.__name__, 'routename with spaces_combined_IRequest' + ) + class Test_add_global_response_headers(unittest.TestCase): def _callFUT(self, request, headerlist): from pyramid.request import add_global_response_headers + return add_global_response_headers(request, headerlist) def test_it(self): @@ -371,11 +423,13 @@ class Test_add_global_response_headers(unittest.TestCase): self._callFUT(request, [('c', 1)]) self.assertEqual(len(request.response_callbacks), 1) request.response_callbacks[0](None, response) - self.assertEqual(response.headerlist, [('c', 1)] ) + self.assertEqual(response.headerlist, [('c', 1)]) + class Test_call_app_with_subpath_as_path_info(unittest.TestCase): def _callFUT(self, request, app): from pyramid.request import call_app_with_subpath_as_path_info + return call_app_with_subpath_as_path_info(request, app) def test_it_all_request_and_environment_data_missing(self): @@ -387,7 +441,7 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/') def test_it_with_subpath_and_path_info(self): - request = DummyRequest({'PATH_INFO':'/hello'}) + request = DummyRequest({'PATH_INFO': '/hello'}) request.subpath = ('hello',) response = self._callFUT(request, 'app') self.assertTrue(request.copied) @@ -396,7 +450,7 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/hello') def test_it_with_subpath_and_path_info_path_info_endswith_slash(self): - request = DummyRequest({'PATH_INFO':'/hello/'}) + request = DummyRequest({'PATH_INFO': '/hello/'}) request.subpath = ('hello',) response = self._callFUT(request, 'app') self.assertTrue(request.copied) @@ -405,7 +459,9 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/hello/') def test_it_with_subpath_and_path_info_extra_script_name(self): - request = DummyRequest({'PATH_INFO':'/hello', 'SCRIPT_NAME':'/script'}) + request = DummyRequest( + {'PATH_INFO': '/hello', 'SCRIPT_NAME': '/script'} + ) request.subpath = ('hello',) response = self._callFUT(request, 'app') self.assertTrue(request.copied) @@ -414,8 +470,9 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/hello') def test_it_with_extra_slashes_in_path_info(self): - request = DummyRequest({'PATH_INFO':'//hello/', - 'SCRIPT_NAME':'/script'}) + request = DummyRequest( + {'PATH_INFO': '//hello/', 'SCRIPT_NAME': '/script'} + ) request.subpath = ('hello',) response = self._callFUT(request, 'app') self.assertTrue(request.copied) @@ -426,15 +483,17 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): def test_subpath_path_info_and_script_name_have_utf8(self): encoded = native_(text_(b'La Pe\xc3\xb1a')) decoded = text_(bytes_(encoded), 'utf-8') - request = DummyRequest({'PATH_INFO':'/' + encoded, - 'SCRIPT_NAME':'/' + encoded}) - request.subpath = (decoded, ) + request = DummyRequest( + {'PATH_INFO': '/' + encoded, 'SCRIPT_NAME': '/' + encoded} + ) + request.subpath = (decoded,) response = self._callFUT(request, 'app') self.assertTrue(request.copied) self.assertEqual(response, 'app') self.assertEqual(request.environ['SCRIPT_NAME'], '/' + encoded) self.assertEqual(request.environ['PATH_INFO'], '/' + encoded) + class Test_apply_request_extensions(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -444,10 +503,12 @@ class Test_apply_request_extensions(unittest.TestCase): def _callFUT(self, request, extensions=None): from pyramid.request import apply_request_extensions + return apply_request_extensions(request, extensions=extensions) def test_it_with_registry(self): from pyramid.interfaces import IRequestExtensions + extensions = Dummy() extensions.methods = {'foo': lambda x, y: y} extensions.descriptors = {'bar': property(lambda x: 'bar')} @@ -460,6 +521,7 @@ class Test_apply_request_extensions(unittest.TestCase): def test_it_override_extensions(self): from pyramid.interfaces import IRequestExtensions + ignore = Dummy() ignore.methods = {'x': lambda x, y, z: 'asdf'} ignore.descriptors = {'bar': property(lambda x: 'asdf')} @@ -475,9 +537,11 @@ class Test_apply_request_extensions(unittest.TestCase): self.assertEqual(request.bar, 'bar') self.assertEqual(request.foo('abc'), 'abc') + class Dummy(object): pass + class Test_subclassing_Request(unittest.TestCase): def test_subclass(self): from pyramid.interfaces import IRequest @@ -497,7 +561,6 @@ class Test_subclassing_Request(unittest.TestCase): # The call to implementedBy will add __provides__ to the class self.assertTrue(hasattr(RequestSub, '__provides__')) - def test_subclass_with_implementer(self): from pyramid.interfaces import IRequest from pyramid.request import Request @@ -554,6 +617,7 @@ class DummyRequest(object): self.copied = True return self + class DummyResponse: def __init__(self): self.headerlist = [] @@ -562,16 +626,20 @@ class DummyResponse: class DummyContext: pass + class DummyRoutesMapper: raise_exc = None + def __init__(self, route=None, raise_exc=False): self.route = route def get_route(self, route_name): return self.route + class DummyRoute: pregenerator = None + def __init__(self, result='/1/2/3'): self.result = result @@ -579,6 +647,7 @@ class DummyRoute: self.kw = kw return self.result + class DummyStaticURLInfo: def __init__(self, result): self.result = result diff --git a/tests/test_response.py b/tests/test_response.py index 53e3ce17a..6ea7125b5 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -4,24 +4,30 @@ import os import unittest from pyramid import testing + class TestResponse(unittest.TestCase): def _getTargetClass(self): from pyramid.response import Response + return Response def test_implements_IResponse(self): from pyramid.interfaces import IResponse + cls = self._getTargetClass() self.assertTrue(IResponse.implementedBy(cls)) def test_provides_IResponse(self): from pyramid.interfaces import IResponse + inst = self._getTargetClass()() self.assertTrue(IResponse.providedBy(inst)) + class TestFileResponse(unittest.TestCase): def _makeOne(self, file, **kw): from pyramid.response import FileResponse + return FileResponse(file, **kw) def _getPath(self, suffix='txt'): @@ -40,8 +46,9 @@ class TestFileResponse(unittest.TestCase): path = self._getPath('xml') r = self._makeOne(path, content_type='application/xml') self.assertEqual(r.content_type, 'application/xml') - self.assertEqual(r.headers['content-type'], - 'application/xml; charset=UTF-8') + self.assertEqual( + r.headers['content-type'], 'application/xml; charset=UTF-8' + ) r.app_iter.close() def test_with_pdf_content_type(self): @@ -55,8 +62,10 @@ class TestFileResponse(unittest.TestCase): for suffix in ('txt', 'xml', 'pdf'): path = self._getPath(suffix) r = self._makeOne(path) - self.assertEqual(r.headers['content-type'].split(';')[0], - mimetypes.guess_type(path, strict=False)[0]) + self.assertEqual( + r.headers['content-type'].split(';')[0], + mimetypes.guess_type(path, strict=False)[0], + ) r.app_iter.close() def test_python_277_bug_15207(self): @@ -67,9 +76,11 @@ class TestFileResponse(unittest.TestCase): from pyramid.compat import text_ import mimetypes as old_mimetypes from pyramid import response + class FakeMimetypesModule(object): - def guess_type(self, *arg, **kw): + def guess_type(self, *arg, **kw): return text_('foo/bar'), None + fake_mimetypes = FakeMimetypesModule() try: response.mimetypes = fake_mimetypes @@ -80,9 +91,11 @@ class TestFileResponse(unittest.TestCase): finally: response.mimetypes = old_mimetypes + class TestFileIter(unittest.TestCase): def _makeOne(self, file, block_size): from pyramid.response import FileIter + return FileIter(file, block_size) def test___iter__(self): @@ -97,7 +110,7 @@ class TestFileIter(unittest.TestCase): r = b'' for x in inst: self.assertEqual(len(x), 1) - r+=x + r += x self.assertEqual(r, data) def test_close(self): @@ -106,15 +119,18 @@ class TestFileIter(unittest.TestCase): inst.close() self.assertTrue(f.closed) + class Test_patch_mimetypes(unittest.TestCase): def _callFUT(self, module): from pyramid.response import init_mimetypes + return init_mimetypes(module) def test_has_init(self): class DummyMimetypes(object): def init(self): self.initted = True + module = DummyMimetypes() result = self._callFUT(module) self.assertEqual(result, True) @@ -123,6 +139,7 @@ class Test_patch_mimetypes(unittest.TestCase): def test_missing_init(self): class DummyMimetypes(object): pass + module = DummyMimetypes() result = self._callFUT(module) self.assertEqual(result, False) @@ -138,13 +155,20 @@ class TestResponseAdapter(unittest.TestCase): def _makeOne(self, *types_or_ifaces, **kw): from pyramid.response import response_adapter + return response_adapter(*types_or_ifaces, **kw) def test_register_single(self): from zope.interface import Interface - class IFoo(Interface): pass + + class IFoo(Interface): + pass + dec = self._makeOne(IFoo) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -153,10 +177,18 @@ class TestResponseAdapter(unittest.TestCase): def test_register_multi(self): from zope.interface import Interface - class IFoo(Interface): pass - class IBar(Interface): pass + + class IFoo(Interface): + pass + + class IBar(Interface): + pass + dec = self._makeOne(IFoo, IBar) - def foo(): pass + + def foo(): + pass + config = DummyConfigurator() scanner = Dummy() scanner.config = config @@ -165,25 +197,39 @@ class TestResponseAdapter(unittest.TestCase): def test___call__(self): from zope.interface import Interface - class IFoo(Interface): pass + + class IFoo(Interface): + pass + dec = self._makeOne(IFoo) dummy_venusian = DummyVenusian() dec.venusian = dummy_venusian - def foo(): pass + + def foo(): + pass + dec(foo) - self.assertEqual(dummy_venusian.attached, - [(foo, dec.register, 'pyramid', 1)]) + self.assertEqual( + dummy_venusian.attached, [(foo, dec.register, 'pyramid', 1)] + ) def test___call___with_venusian_args(self): from zope.interface import Interface - class IFoo(Interface): pass + + class IFoo(Interface): + pass + dec = self._makeOne(IFoo, _category='foo', _depth=1) dummy_venusian = DummyVenusian() dec.venusian = dummy_venusian - def foo(): pass + + def foo(): + pass + dec(foo) - self.assertEqual(dummy_venusian.attached, - [(foo, dec.register, 'foo', 2)]) + self.assertEqual( + dummy_venusian.attached, [(foo, dec.register, 'foo', 2)] + ) class TestGetResponseFactory(unittest.TestCase): @@ -199,6 +245,7 @@ class TestGetResponseFactory(unittest.TestCase): class Dummy(object): pass + class DummyConfigurator(object): def __init__(self): self.adapters = [] @@ -206,6 +253,7 @@ class DummyConfigurator(object): def add_response_adapter(self, wrapped, type_or_iface): self.adapters.append((wrapped, type_or_iface)) + class DummyVenusian(object): def __init__(self): self.attached = [] diff --git a/tests/test_router.py b/tests/test_router.py index 6097018f0..f06cfe5bc 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -2,6 +2,7 @@ import unittest from pyramid import testing + class TestRouter(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -13,6 +14,7 @@ class TestRouter(unittest.TestCase): def _registerRouteRequest(self, name): from pyramid.interfaces import IRouteRequest from pyramid.request import route_request_iface + iface = route_request_iface(name) self.registry.registerUtility(iface, IRouteRequest, name=name) return iface @@ -20,6 +22,7 @@ class TestRouter(unittest.TestCase): def _connectRoute(self, name, path, factory=None): from pyramid.interfaces import IRoutesMapper from pyramid.urldispatch import RoutesMapper + mapper = self.registry.queryUtility(IRoutesMapper) if mapper is None: mapper = RoutesMapper() @@ -28,21 +31,31 @@ class TestRouter(unittest.TestCase): def _registerLogger(self): from pyramid.interfaces import IDebugLogger + logger = DummyLogger() self.registry.registerUtility(logger, IDebugLogger) return logger def _registerSettings(self, **kw): - settings = {'debug_authorization':False, - 'debug_notfound':False, - 'debug_routematch':False} + settings = { + 'debug_authorization': False, + 'debug_notfound': False, + 'debug_routematch': False, + } settings.update(kw) self.registry.settings = settings - def _registerTraverserFactory(self, context, view_name='', subpath=None, - traversed=None, virtual_root=None, - virtual_root_path=None, raise_error=None, - **kw): + def _registerTraverserFactory( + self, + context, + view_name='', + subpath=None, + traversed=None, + virtual_root=None, + virtual_root_path=None, + raise_error=None, + **kw + ): from pyramid.interfaces import ITraverser if virtual_root is None: @@ -61,39 +74,48 @@ class TestRouter(unittest.TestCase): def __call__(self, request): if raise_error: raise raise_error - values = {'root':self.root, - 'context':context, - 'view_name':view_name, - 'subpath':subpath, - 'traversed':traversed, - 'virtual_root':virtual_root, - 'virtual_root_path':virtual_root_path} + values = { + 'root': self.root, + 'context': context, + 'view_name': view_name, + 'subpath': subpath, + 'traversed': traversed, + 'virtual_root': virtual_root, + 'virtual_root_path': virtual_root_path, + } kw.update(values) return kw - self.registry.registerAdapter(DummyTraverserFactory, (None,), - ITraverser, name='') + self.registry.registerAdapter( + DummyTraverserFactory, (None,), ITraverser, name='' + ) def _registerView(self, app, name, classifier, req_iface, ctx_iface): from pyramid.interfaces import IView + self.registry.registerAdapter( - app, (classifier, req_iface, ctx_iface), IView, name) + app, (classifier, req_iface, ctx_iface), IView, name + ) def _registerEventListener(self, iface): L = [] + def listener(event): L.append(event) + self.registry.registerHandler(listener, (iface,)) return L def _registerRootFactory(self, val): rootfactory = DummyRootFactory(val) from pyramid.interfaces import IRootFactory + self.registry.registerUtility(rootfactory, IRootFactory) return rootfactory def _getTargetClass(self): from pyramid.router import Router + return Router def _makeOne(self): @@ -102,12 +124,12 @@ class TestRouter(unittest.TestCase): def _makeEnviron(self, **extras): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'localhost', - 'SERVER_PORT':'8080', - 'REQUEST_METHOD':'GET', - 'PATH_INFO':'/', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'localhost', + 'SERVER_PORT': '8080', + 'REQUEST_METHOD': 'GET', + 'PATH_INFO': '/', + } environ.update(extras) return environ @@ -128,8 +150,10 @@ class TestRouter(unittest.TestCase): def test_request_factory(self): from pyramid.interfaces import IRequestFactory + class DummyRequestFactory(object): pass + self.registry.registerUtility(DummyRequestFactory, IRequestFactory) router = self._makeOne() self.assertEqual(router.request_factory, DummyRequestFactory) @@ -140,41 +164,53 @@ class TestRouter(unittest.TestCase): from pyramid.response import Response from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IResponse + tweens = Tweens() self.registry.registerUtility(tweens, ITweens) L = [] + def tween_factory1(handler, registry): L.append((handler, registry)) + def wrapper(request): request.environ['handled'].append('one') return handler(request) + wrapper.name = 'one' wrapper.child = handler return wrapper + def tween_factory2(handler, registry): L.append((handler, registry)) + def wrapper(request): request.environ['handled'] = ['two'] return handler(request) + wrapper.name = 'two' wrapper.child = handler return wrapper + tweens.add_implicit('one', tween_factory1) tweens.add_implicit('two', tween_factory2) router = self._makeOne() self.assertEqual(router.handle_request.name, 'two') self.assertEqual(router.handle_request.child.name, 'one') - self.assertEqual(router.handle_request.child.child.__name__, - 'handle_request') + self.assertEqual( + router.handle_request.child.child.__name__, 'handle_request' + ) context = DummyContext() self._registerTraverserFactory(context) environ = self._makeEnviron() view = DummyView('abc') - self._registerView(self.config.derive_view(view), '', - IViewClassifier, None, None) + self._registerView( + self.config.derive_view(view), '', IViewClassifier, None, None + ) start_response = DummyStartResponse() + def make_response(s): return Response(s) + router.registry.registerAdapter(make_response, (str,), IResponse) app_iter = router(environ, start_response) self.assertEqual(app_iter, [b'abc']) @@ -183,6 +219,7 @@ class TestRouter(unittest.TestCase): def test_call_traverser_default(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() logger = self._registerLogger() router = self._makeOne() @@ -194,6 +231,7 @@ class TestRouter(unittest.TestCase): def test_traverser_raises_notfound_class(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context, raise_error=HTTPNotFound) @@ -203,9 +241,12 @@ class TestRouter(unittest.TestCase): def test_traverser_raises_notfound_instance(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() context = DummyContext() - self._registerTraverserFactory(context, raise_error=HTTPNotFound('foo')) + self._registerTraverserFactory( + context, raise_error=HTTPNotFound('foo') + ) router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) @@ -213,6 +254,7 @@ class TestRouter(unittest.TestCase): def test_traverser_raises_forbidden_class(self): from pyramid.httpexceptions import HTTPForbidden + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context, raise_error=HTTPForbidden) @@ -222,10 +264,12 @@ class TestRouter(unittest.TestCase): def test_traverser_raises_forbidden_instance(self): from pyramid.httpexceptions import HTTPForbidden + environ = self._makeEnviron() context = DummyContext() - self._registerTraverserFactory(context, - raise_error=HTTPForbidden('foo')) + self._registerTraverserFactory( + context, raise_error=HTTPForbidden('foo') + ) router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPForbidden, router, environ, start_response) @@ -233,6 +277,7 @@ class TestRouter(unittest.TestCase): def test_call_no_view_registered_no_isettings(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context) @@ -246,6 +291,7 @@ class TestRouter(unittest.TestCase): def test_call_no_view_registered_debug_notfound_false(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context) @@ -260,6 +306,7 @@ class TestRouter(unittest.TestCase): def test_call_no_view_registered_debug_notfound_true(self): from pyramid.httpexceptions import HTTPNotFound + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context) @@ -269,7 +316,8 @@ class TestRouter(unittest.TestCase): start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) self.assertTrue( - "debug_notfound of url http://localhost:8080/; " in why.args[0]) + "debug_notfound of url http://localhost:8080/; " in why.args[0] + ) self.assertTrue("view_name: '', subpath: []" in why.args[0]) self.assertTrue('http://localhost:8080' in why.args[0], why) @@ -283,12 +331,14 @@ class TestRouter(unittest.TestCase): def test_call_view_returns_non_iresponse(self): from pyramid.interfaces import IViewClassifier + context = DummyContext() self._registerTraverserFactory(context) environ = self._makeEnviron() view = DummyView('abc') - self._registerView(self.config.derive_view(view), '', IViewClassifier, - None, None) + self._registerView( + self.config.derive_view(view), '', IViewClassifier, None, None + ) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(ValueError, router, environ, start_response) @@ -297,16 +347,20 @@ class TestRouter(unittest.TestCase): from pyramid.response import Response from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IResponse + context = DummyContext() self._registerTraverserFactory(context) environ = self._makeEnviron() view = DummyView('abc') - self._registerView(self.config.derive_view(view), '', - IViewClassifier, None, None) + self._registerView( + self.config.derive_view(view), '', IViewClassifier, None, None + ) router = self._makeOne() start_response = DummyStartResponse() + def make_response(s): return Response(s) + router.registry.registerAdapter(make_response, (str,), IResponse) app_iter = router(environ, start_response) self.assertEqual(app_iter, [b'abc']) @@ -318,12 +372,15 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.request import Request from pyramid.util import InstancePropertyHelper + context = DummyContext() self._registerTraverserFactory(context) + class Extensions(object): def __init__(self): self.methods = {} self.descriptors = {} + extensions = Extensions() ext_method = lambda r: 'bar' name, fn = InstancePropertyHelper.make_property(ext_method, name='foo') @@ -331,15 +388,18 @@ class TestRouter(unittest.TestCase): request = Request.blank('/') request.request_iface = IRequest request.registry = self.registry + def request_factory(environ): return request + self.registry.registerUtility(extensions, IRequestExtensions) environ = self._makeEnviron() response = DummyResponse() response.app_iter = ['Hello world'] view = DummyView(response) - self._registerView(self.config.derive_view(view), '', - IViewClassifier, None, None) + self._registerView( + self.config.derive_view(view), '', IViewClassifier, None, None + ) router = self._makeOne() router.request_factory = request_factory start_response = DummyStartResponse() @@ -348,14 +408,16 @@ class TestRouter(unittest.TestCase): def test_call_view_registered_nonspecific_default_path(self): from pyramid.interfaces import IViewClassifier + context = DummyContext() self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] view = DummyView(response) environ = self._makeEnviron() - self._registerView(self.config.derive_view(view), '', - IViewClassifier, None, None) + self._registerView( + self.config.derive_view(view), '', IViewClassifier, None, None + ) self._registerRootFactory(context) router = self._makeOne() start_response = DummyStartResponse() @@ -369,12 +431,15 @@ class TestRouter(unittest.TestCase): self.assertEqual(request.context, context) self.assertEqual(request.root, context) - def test_call_view_registered_nonspecific_nondefault_path_and_subpath(self): + def test_call_view_registered_nonspecific_nondefault_path_and_subpath( + self + ): from pyramid.interfaces import IViewClassifier + context = DummyContext() - self._registerTraverserFactory(context, view_name='foo', - subpath=['bar'], - traversed=['context']) + self._registerTraverserFactory( + context, view_name='foo', subpath=['bar'], traversed=['context'] + ) self._registerRootFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] @@ -396,10 +461,13 @@ class TestRouter(unittest.TestCase): def test_call_view_registered_specific_success(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context) @@ -426,11 +494,15 @@ class TestRouter(unittest.TestCase): from zope.interface import directlyProvides from pyramid.httpexceptions import HTTPNotFound from pyramid.interfaces import IViewClassifier + class IContext(Interface): pass + class INotContext(Interface): pass + from pyramid.interfaces import IRequest + context = DummyContext() directlyProvides(context, INotContext) self._registerTraverserFactory(context, subpath=['']) @@ -446,16 +518,20 @@ class TestRouter(unittest.TestCase): from zope.interface import Interface from zope.interface import directlyProvides from pyramid.httpexceptions import HTTPForbidden + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = DummyView(response, - raise_exception=HTTPForbidden("unauthorized")) + view = DummyView( + response, raise_exception=HTTPForbidden("unauthorized") + ) environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) router = self._makeOne() @@ -466,11 +542,14 @@ class TestRouter(unittest.TestCase): def test_call_view_raises_notfound(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier from pyramid.httpexceptions import HTTPNotFound + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) @@ -487,24 +566,31 @@ class TestRouter(unittest.TestCase): from zope.interface import Interface from zope.interface import directlyProvides from pyramid.interfaces import IExceptionViewClassifier + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) + def view(context, request): request.response.a = 1 raise KeyError + def exc_view(context, request): self.assertFalse(hasattr(request.response, 'a')) request.response.body = b'OK' return request.response + environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) - self._registerView(exc_view, '', IExceptionViewClassifier, - IRequest, KeyError) + self._registerView( + exc_view, '', IExceptionViewClassifier, IRequest, KeyError + ) router = self._makeOne() start_response = DummyStartResponse() itera = router(environ, start_response) @@ -513,19 +599,25 @@ class TestRouter(unittest.TestCase): def test_call_request_has_response_callbacks(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse('200 OK') + def view(context, request): def callback(request, response): response.called_back = True + request.add_response_callback(callback) return response + environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) router = self._makeOne() @@ -536,19 +628,25 @@ class TestRouter(unittest.TestCase): def test_call_request_has_finished_callbacks_when_view_succeeds(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse('200 OK') + def view(context, request): def callback(request): request.environ['called_back'] = True + request.add_finished_callback(callback) return response + environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) router = self._makeOne() @@ -559,18 +657,24 @@ class TestRouter(unittest.TestCase): def test_call_request_has_finished_callbacks_when_view_raises(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier + context = DummyContext() directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) + def view(context, request): def callback(request): request.environ['called_back'] = True + request.add_finished_callback(callback) raise NotImplementedError + environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) router = self._makeOne() @@ -582,8 +686,10 @@ class TestRouter(unittest.TestCase): # making sure finally doesnt barf when a request cannot be created environ = self._makeEnviron() router = self._makeOne() + def dummy_request_factory(environ): raise NotImplementedError + router.request_factory = dummy_request_factory start_response = DummyStartResponse() exc_raised(NotImplementedError, router, environ, start_response) @@ -594,6 +700,7 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IBeforeTraversal from pyramid.interfaces import IContextFound from pyramid.interfaces import IViewClassifier + context = DummyContext() self._registerTraverserFactory(context) response = DummyResponse() @@ -624,18 +731,22 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import INewRequest from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + context = DummyContext() self._registerTraverserFactory(context) environ = self._makeEnviron() + def listener(event): raise KeyError + self.registry.registerHandler(listener, (INewRequest,)) exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] exception_view = DummyView(exception_response) environ = self._makeEnviron() - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, KeyError) + self._registerView( + exception_view, '', IExceptionViewClassifier, IRequest, KeyError + ) router = self._makeOne() start_response = DummyStartResponse() result = router(environ, start_response) @@ -643,12 +754,15 @@ class TestRouter(unittest.TestCase): def test_call_route_matches_and_has_factory(self): from pyramid.interfaces import IViewClassifier + logger = self._registerLogger() self._registerSettings(debug_routematch=True) self._registerRouteRequest('foo') root = object() + def factory(request): return root + route = self._connectRoute('foo', 'archives/:action/:article', factory) route.predicates = [DummyPredicate()] context = DummyContext() @@ -670,23 +784,23 @@ class TestRouter(unittest.TestCase): self.assertEqual(request.subpath, []) self.assertEqual(request.context, context) self.assertEqual(request.root, root) - matchdict = {'action':'action1', 'article':'article1'} + matchdict = {'action': 'action1', 'article': 'article1'} self.assertEqual(request.matchdict, matchdict) self.assertEqual(request.matched_route.name, 'foo') self.assertEqual(len(logger.messages), 1) self.assertTrue( logger.messages[0].startswith( - "route matched for url http://localhost:8080" - "/archives/action1/article1; " - "route_name: 'foo', " - "path_info: ") - ) - self.assertTrue( - "predicates: 'predicate'" in logger.messages[0] + "route matched for url http://localhost:8080" + "/archives/action1/article1; " + "route_name: 'foo', " + "path_info: " ) + ) + self.assertTrue("predicates: 'predicate'" in logger.messages[0]) def test_call_route_match_miss_debug_routematch(self): from pyramid.httpexceptions import HTTPNotFound + logger = self._registerLogger() self._registerSettings(debug_routematch=True) self._registerRouteRequest('foo') @@ -702,22 +816,29 @@ class TestRouter(unittest.TestCase): self.assertEqual(len(logger.messages), 1) self.assertEqual( logger.messages[0], - 'no route matched for url http://localhost:8080/wontmatch') + 'no route matched for url http://localhost:8080/wontmatch', + ) def test_call_route_matches_doesnt_overwrite_subscriber_iface(self): from pyramid.interfaces import INewRequest from pyramid.interfaces import IViewClassifier from zope.interface import alsoProvides from zope.interface import Interface + self._registerRouteRequest('foo') + class IFoo(Interface): pass + def listener(event): alsoProvides(event.request, IFoo) + self.registry.registerHandler(listener, (INewRequest,)) root = object() + def factory(request): return root + self._connectRoute('foo', 'archives/:action/:article', factory) context = DummyContext() self._registerTraverserFactory(context) @@ -738,7 +859,7 @@ class TestRouter(unittest.TestCase): self.assertEqual(request.subpath, []) self.assertEqual(request.context, context) self.assertEqual(request.root, root) - matchdict = {'action':'action1', 'article':'article1'} + matchdict = {'action': 'action1', 'article': 'article1'} self.assertEqual(request.matchdict, matchdict) self.assertEqual(request.matched_route.name, 'foo') self.assertTrue(IFoo.providedBy(request)) @@ -748,11 +869,15 @@ class TestRouter(unittest.TestCase): from pyramid.httpexceptions import HTTPNotFound from zope.interface import Interface from zope.interface import directlyProvides + def rootfactory(request): raise HTTPNotFound('from root factory') + self.registry.registerUtility(rootfactory, IRootFactory) + class IContext(Interface): pass + context = DummyContext() directlyProvides(context, IContext) environ = self._makeEnviron() @@ -766,11 +891,15 @@ class TestRouter(unittest.TestCase): from pyramid.httpexceptions import HTTPForbidden from zope.interface import Interface from zope.interface import directlyProvides + def rootfactory(request): raise HTTPForbidden('from root factory') + self.registry.registerUtility(rootfactory, IRootFactory) + class IContext(Interface): pass + context = DummyContext() directlyProvides(context, IContext) environ = self._makeEnviron() @@ -783,11 +912,15 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRootFactory from zope.interface import Interface from zope.interface import directlyProvides + def rootfactory(request): raise RuntimeError() + self.registry.registerUtility(rootfactory, IRootFactory) + class IContext(Interface): pass + context = DummyContext() directlyProvides(context, IContext) environ = self._makeEnviron() @@ -806,16 +939,21 @@ class TestRouter(unittest.TestCase): def test_call_view_exception_propagating(self): from zope.interface import Interface from zope.interface import directlyProvides + class IContext(Interface): pass + from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IRequestFactory from pyramid.interfaces import IExceptionViewClassifier + def rfactory(environ): return request + self.registry.registerUtility(rfactory, IRequestFactory) from pyramid.request import Request + request = Request.blank('/') context = DummyContext() directlyProvides(context, IContext) @@ -825,12 +963,19 @@ class TestRouter(unittest.TestCase): error = RuntimeError() view = DummyView(response, raise_exception=error) environ = self._makeEnviron() + def exception_view(context, request): self.assertEqual(request.exc_info[0], RuntimeError) return response + self._registerView(view, '', IViewClassifier, IRequest, IContext) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) router = self._makeOne() start_response = DummyStartResponse() result = router(environ, start_response) @@ -839,23 +984,31 @@ class TestRouter(unittest.TestCase): # the excview tween has run (see # https://github.com/Pylons/pyramid/issues/1223) self.assertEqual(request.exception, error) - self.assertEqual(request.exc_info[:2], (RuntimeError, error,)) - + self.assertEqual(request.exc_info[:2], (RuntimeError, error)) + def test_call_view_raises_exception_view(self): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + response = DummyResponse() exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] view = DummyView(response, raise_exception=RuntimeError) + def exception_view(context, request): self.assertEqual(request.exception.__class__, RuntimeError) return exception_response + environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, None) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) router = self._makeOne() start_response = DummyStartResponse() result = router(environ, start_response) @@ -865,10 +1018,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class SuperException(Exception): pass + class SubException(SuperException): pass + response = DummyResponse() exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] @@ -876,8 +1032,13 @@ class TestRouter(unittest.TestCase): exception_view = DummyView(exception_response) environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, None) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, SubException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + SubException, + ) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(SuperException, router, environ, start_response) @@ -886,10 +1047,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class SuperException(Exception): pass + class SubException(SuperException): pass + response = DummyResponse() exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] @@ -897,8 +1061,13 @@ class TestRouter(unittest.TestCase): exception_view = DummyView(exception_response) environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, None) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, SuperException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + SuperException, + ) router = self._makeOne() start_response = DummyStartResponse() result = router(environ, start_response) @@ -908,10 +1077,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class MyException(Exception): pass + class AnotherException(Exception): pass + response = DummyResponse() exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] @@ -919,8 +1091,13 @@ class TestRouter(unittest.TestCase): exception_view = DummyView(exception_response) environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, None) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, AnotherException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + AnotherException, + ) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(MyException, router, environ, start_response) @@ -929,14 +1106,21 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRootFactory from pyramid.interfaces import IRequest from pyramid.interfaces import IExceptionViewClassifier + def rootfactory(request): raise RuntimeError() + self.registry.registerUtility(rootfactory, IRootFactory) exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] exception_view = DummyView(exception_response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) environ = self._makeEnviron() router = self._makeOne() start_response = DummyStartResponse() @@ -946,14 +1130,20 @@ class TestRouter(unittest.TestCase): def test_traverser_raises_exception_view(self): from pyramid.interfaces import IRequest from pyramid.interfaces import IExceptionViewClassifier + environ = self._makeEnviron() context = DummyContext() self._registerTraverserFactory(context, raise_error=RuntimeError()) exception_response = DummyResponse() exception_response.app_iter = ["Hello, world"] exception_view = DummyView(exception_response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) router = self._makeOne() start_response = DummyStartResponse() result = router(environ, start_response) @@ -963,16 +1153,22 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + environ = self._makeEnviron() response = DummyResponse() view = DummyView(response, raise_exception=RuntimeError) - - self._registerView(self.config.derive_view(view), '', - IViewClassifier, IRequest, None) + + self._registerView( + self.config.derive_view(view), '', IViewClassifier, IRequest, None + ) exception_view = DummyView(None) - self._registerView(self.config.derive_view(exception_view), '', - IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + self.config.derive_view(exception_view), + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(ValueError, router, environ, start_response) @@ -980,6 +1176,7 @@ class TestRouter(unittest.TestCase): def test_call_route_raises_route_exception_view(self): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=RuntimeError) @@ -987,8 +1184,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - req_iface, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + req_iface, + RuntimeError, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -999,6 +1201,7 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=RuntimeError) @@ -1006,8 +1209,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - req_iface, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + req_iface, + RuntimeError, + ) environ = self._makeEnviron() start_response = DummyStartResponse() router = self._makeOne() @@ -1017,6 +1225,7 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=RuntimeError) @@ -1024,8 +1233,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1036,10 +1250,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class SuperException(Exception): pass + class SubException(SuperException): pass + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=SuperException) @@ -1047,8 +1264,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, SubException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + SubException, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1058,10 +1280,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class SuperException(Exception): pass + class SubException(SuperException): pass + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=SubException) @@ -1069,8 +1294,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, SuperException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + SuperException, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1081,10 +1311,13 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class MyException(Exception): pass + class AnotherException(Exception): pass + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=MyException) @@ -1092,8 +1325,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, AnotherException) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + AnotherException, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1103,6 +1341,7 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=RuntimeError) @@ -1110,13 +1349,23 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - IRequest, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + IRequest, + RuntimeError, + ) response_spec = DummyResponse() response_spec.app_iter = ["Hello, special world"] exception_view_spec = DummyView(response_spec) - self._registerView(exception_view_spec, '', IExceptionViewClassifier, - req_iface, RuntimeError) + self._registerView( + exception_view_spec, + '', + IExceptionViewClassifier, + req_iface, + RuntimeError, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1126,6 +1375,7 @@ class TestRouter(unittest.TestCase): def test_call_route_raises_exception_view_another_route(self): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + req_iface = self._registerRouteRequest('foo') another_req_iface = self._registerRouteRequest('bar') self._connectRoute('foo', 'archives/:action/:article', None) @@ -1134,8 +1384,13 @@ class TestRouter(unittest.TestCase): response = DummyResponse() response.app_iter = ["Hello, world"] exception_view = DummyView(response) - self._registerView(exception_view, '', IExceptionViewClassifier, - another_req_iface, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + another_req_iface, + RuntimeError, + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1145,6 +1400,7 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier + req_iface = self._registerRouteRequest('foo') response = DummyResponse() exception_response = DummyResponse() @@ -1153,8 +1409,13 @@ class TestRouter(unittest.TestCase): exception_view = DummyView(exception_response) environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, None) - self._registerView(exception_view, '', IExceptionViewClassifier, - req_iface, RuntimeError) + self._registerView( + exception_view, + '', + IExceptionViewClassifier, + req_iface, + RuntimeError, + ) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(RuntimeError, router, environ, start_response) @@ -1163,6 +1424,7 @@ class TestRouter(unittest.TestCase): from pyramid.exceptions import PredicateMismatch from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IRequest + view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) self._registerView(view, '', IViewClassifier, IRequest, None) environ = self._makeEnviron() @@ -1175,21 +1437,30 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IRequest, IResponse from pyramid.response import Response + class BaseContext: pass + class DummyContext(BaseContext): pass + context = DummyContext() self._registerTraverserFactory(context) view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) - self._registerView(view, '', IViewClassifier, IRequest, - DummyContext) + self._registerView(view, '', IViewClassifier, IRequest, DummyContext) good_view = DummyView('abc') - self._registerView(self.config.derive_view(good_view), - '', IViewClassifier, IRequest, BaseContext) + self._registerView( + self.config.derive_view(good_view), + '', + IViewClassifier, + IRequest, + BaseContext, + ) router = self._makeOne() + def make_response(s): return Response(s) + router.registry.registerAdapter(make_response, (str,), IResponse) environ = self._makeEnviron() start_response = DummyStartResponse() @@ -1202,27 +1473,36 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IRequest, IResponse from pyramid.response import Response from zope.interface import Interface, implementer + class IBaseContext(Interface): pass + class IContext(IBaseContext): pass + @implementer(IContext) class DummyContext: pass + context = DummyContext() self._registerTraverserFactory(context) view1 = DummyView(DummyResponse(), raise_exception=PredicateMismatch) - self._registerView(view1, '', IViewClassifier, IRequest, - DummyContext) + self._registerView(view1, '', IViewClassifier, IRequest, DummyContext) view2 = DummyView(DummyResponse(), raise_exception=PredicateMismatch) - self._registerView(view2, '', IViewClassifier, IRequest, - IContext) + self._registerView(view2, '', IViewClassifier, IRequest, IContext) good_view = DummyView('abc') - self._registerView(self.config.derive_view(good_view), - '', IViewClassifier, IRequest, IBaseContext) + self._registerView( + self.config.derive_view(good_view), + '', + IViewClassifier, + IRequest, + IBaseContext, + ) router = self._makeOne() + def make_response(s): return Response(s) + router.registry.registerAdapter(make_response, (str,), IResponse) environ = self._makeEnviron() start_response = DummyStartResponse() @@ -1234,21 +1514,29 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IRequest from zope.interface import Interface, implementer + class IContext(Interface): pass + class IOtherContext(Interface): pass + @implementer(IContext) class DummyContext: pass + context = DummyContext() self._registerTraverserFactory(context) view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) - self._registerView(view, '', IViewClassifier, IRequest, - DummyContext) + self._registerView(view, '', IViewClassifier, IRequest, DummyContext) please_dont_call_me_view = DummyView('abc') - self._registerView(self.config.derive_view(please_dont_call_me_view), - '', IViewClassifier, IRequest, IOtherContext) + self._registerView( + self.config.derive_view(please_dont_call_me_view), + '', + IViewClassifier, + IRequest, + IOtherContext, + ) router = self._makeOne() environ = self._makeEnviron() router = self._makeOne() @@ -1259,9 +1547,12 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IExecutionPolicy from pyramid.request import Request from pyramid.response import Response + registry = self.config.registry + def dummy_policy(environ, router): return Response(status=200, body=b'foo') + registry.registerUtility(dummy_policy, IExecutionPolicy) router = self._makeOne() resp = Request.blank('/').get_response(router) @@ -1272,23 +1563,29 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IRequest + class Exception1(Exception): pass + class Exception2(Exception): pass + req_iface = self._registerRouteRequest('foo') self._connectRoute('foo', 'archives/:action/:article', None) view = DummyView(DummyResponse(), raise_exception=Exception1) self._registerView(view, '', IViewClassifier, req_iface, None) - exception_view1 = DummyView(DummyResponse(), - raise_exception=Exception2) - self._registerView(exception_view1, '', IExceptionViewClassifier, - IRequest, Exception1) + exception_view1 = DummyView( + DummyResponse(), raise_exception=Exception2 + ) + self._registerView( + exception_view1, '', IExceptionViewClassifier, IRequest, Exception1 + ) response = DummyResponse() response.app_iter = ["Hello, world"] exception_view2 = DummyView(response) - self._registerView(exception_view2, '', IExceptionViewClassifier, - IRequest, Exception2) + self._registerView( + exception_view2, '', IExceptionViewClassifier, IRequest, Exception2 + ) environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') start_response = DummyStartResponse() router = self._makeOne() @@ -1300,13 +1597,16 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IExecutionPolicy from pyramid.request import Request from pyramid.response import Response + registry = self.config.registry result = [] + def dummy_policy(environ, router): with router.request_context(environ): result.append(get_current_request()) result.append(get_current_request()) return Response(status=200, body=b'foo') + registry.registerUtility(dummy_policy, IExecutionPolicy) router = self._makeOne() resp = Request.blank('/test_path').get_response(router) @@ -1320,8 +1620,10 @@ class TestRouter(unittest.TestCase): from pyramid.interfaces import IExecutionPolicy from pyramid.request import Request from pyramid.response import Response + registry = self.config.registry result = [] + def dummy_policy(environ, router): ctx = router.request_context(environ) ctx.begin() @@ -1329,6 +1631,7 @@ class TestRouter(unittest.TestCase): ctx.end() result.append(get_current_request()) return Response(status=200, body=b'foo') + registry.registerUtility(dummy_policy, IExecutionPolicy) router = self._makeOne() resp = Request.blank('/test_path').get_response(router) @@ -1337,15 +1640,19 @@ class TestRouter(unittest.TestCase): self.assertEqual(result[0].path_info, '/test_path') self.assertEqual(result[1], None) + class DummyPredicate(object): def __call__(self, info, request): return True + def text(self): return 'predicate' + class DummyContext: pass + class DummyView: def __init__(self, response, raise_exception=None): self.response = response @@ -1358,6 +1665,7 @@ class DummyView: raise self.raise_exception return self.response + class DummyRootFactory: def __init__(self, root): self.root = root @@ -1365,21 +1673,26 @@ class DummyRootFactory: def __call__(self, environ): return self.root + class DummyStartResponse: status = () headers = () + def __call__(self, status, headers): self.status = status self.headers = headers + from pyramid.interfaces import IResponse from zope.interface import implementer + @implementer(IResponse) class DummyResponse(object): headerlist = () app_iter = () environ = None + def __init__(self, status='200 OK'): self.status = status @@ -1387,24 +1700,27 @@ class DummyResponse(object): self.environ = environ start_response(self.status, self.headerlist) return self.app_iter - + + class DummyAuthenticationPolicy: pass + class DummyLogger: def __init__(self): self.messages = [] + def info(self, msg): self.messages.append(msg) + warn = info debug = info + def exc_raised(exc, func, *arg, **kw): try: func(*arg, **kw) except exc as e: return e else: - raise AssertionError('%s not raised' % exc) # pragma: no cover - - + raise AssertionError('%s not raised' % exc) # pragma: no cover diff --git a/tests/test_scaffolds/test_copydir.py b/tests/test_scaffolds/test_copydir.py index 915cc5033..1f046f9e8 100644 --- a/tests/test_scaffolds/test_copydir.py +++ b/tests/test_scaffolds/test_copydir.py @@ -3,39 +3,47 @@ import unittest import os import pkg_resources + class Test_copy_dir(unittest.TestCase): def setUp(self): import tempfile from pyramid.compat import NativeIO + self.dirname = tempfile.mkdtemp() self.out = NativeIO() - self.fixturetuple = ('tests.test_scaffolds', - 'fixture_scaffold') + self.fixturetuple = ('tests.test_scaffolds', 'fixture_scaffold') def tearDown(self): import shutil + shutil.rmtree(self.dirname, ignore_errors=True) self.out.close() def _callFUT(self, *arg, **kw): kw['out_'] = self.out from pyramid.scaffolds.copydir import copy_dir + return copy_dir(*arg, **kw) def test_copy_source_as_pkg_resource(self): - vars = {'package':'mypackage'} - self._callFUT(self.fixturetuple, - self.dirname, - vars, - 1, False, - template_renderer=dummy_template_renderer) + vars = {'package': 'mypackage'} + self._callFUT( + self.fixturetuple, + self.dirname, + vars, + 1, + False, + template_renderer=dummy_template_renderer, + ) result = self.out.getvalue() self.assertTrue('Creating' in result) self.assertTrue( - 'Copying fixture_scaffold/+package+/__init__.py_tmpl to' in result) + 'Copying fixture_scaffold/+package+/__init__.py_tmpl to' in result + ) source = pkg_resources.resource_filename( 'tests.test_scaffolds', - 'fixture_scaffold/+package+/__init__.py_tmpl') + 'fixture_scaffold/+package+/__init__.py_tmpl', + ) target = os.path.join(self.dirname, 'mypackage', '__init__.py') with open(target, 'r') as f: tcontent = f.read() @@ -44,19 +52,23 @@ class Test_copy_dir(unittest.TestCase): self.assertEqual(scontent, tcontent) def test_copy_source_as_dirname(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) - self._callFUT(source, - self.dirname, - vars, - 1, False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + template_renderer=dummy_template_renderer, + ) result = self.out.getvalue() self.assertTrue('Creating' in result) self.assertTrue('Copying __init__.py_tmpl to' in result) source = pkg_resources.resource_filename( 'tests.test_scaffolds', - 'fixture_scaffold/+package+/__init__.py_tmpl') + 'fixture_scaffold/+package+/__init__.py_tmpl', + ) target = os.path.join(self.dirname, 'mypackage', '__init__.py') with open(target, 'r') as f: tcontent = f.read() @@ -65,58 +77,78 @@ class Test_copy_dir(unittest.TestCase): self.assertEqual(scontent, tcontent) def test_content_is_same_message(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) - self._callFUT(source, - self.dirname, - vars, - 2, False, - template_renderer=dummy_template_renderer) - self._callFUT(source, - self.dirname, - vars, - 2, False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 2, + False, + template_renderer=dummy_template_renderer, + ) + self._callFUT( + source, + self.dirname, + vars, + 2, + False, + template_renderer=dummy_template_renderer, + ) result = self.out.getvalue() - self.assertTrue('%s already exists (same content)' % \ - os.path.join(self.dirname, 'mypackage', '__init__.py') in result) + self.assertTrue( + '%s already exists (same content)' + % os.path.join(self.dirname, 'mypackage', '__init__.py') + in result + ) def test_direxists_message(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) # if not os.path.exists(self.dirname): # os.mkdir(self.dirname) - self._callFUT(source, - self.dirname, - vars, - 2, False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 2, + False, + template_renderer=dummy_template_renderer, + ) result = self.out.getvalue() self.assertTrue('Directory %s exists' % self.dirname in result, result) def test_overwrite_false(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) - self._callFUT(source, - self.dirname, - vars, - 1, False, - overwrite=False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + overwrite=False, + template_renderer=dummy_template_renderer, + ) # toplevel file toplevel = os.path.join(self.dirname, 'mypackage', '__init__.py') with open(toplevel, 'w') as f: f.write('These are the words you are looking for.') # sub directory file - sub = os.path.join(self.dirname, 'mypackage', 'templates', 'mytemplate.pt') + sub = os.path.join( + self.dirname, 'mypackage', 'templates', 'mytemplate.pt' + ) with open(sub, 'w') as f: f.write('These are the words you are looking for.') - self._callFUT(source, - self.dirname, - vars, - 1, False, - overwrite=False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + overwrite=False, + template_renderer=dummy_template_renderer, + ) with open(toplevel, 'r') as f: tcontent = f.read() self.assertEqual('These are the words you are looking for.', tcontent) @@ -125,57 +157,79 @@ class Test_copy_dir(unittest.TestCase): self.assertEqual('These are the words you are looking for.', tcontent) def test_overwrite_true(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) - self._callFUT(source, - self.dirname, - vars, - 1, False, - overwrite=True, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + overwrite=True, + template_renderer=dummy_template_renderer, + ) # toplevel file toplevel = os.path.join(self.dirname, 'mypackage', '__init__.py') with open(toplevel, 'w') as f: f.write('These are not the words you are looking for.') # sub directory file - sub = os.path.join(self.dirname, 'mypackage', 'templates', 'mytemplate.pt') + sub = os.path.join( + self.dirname, 'mypackage', 'templates', 'mytemplate.pt' + ) with open(sub, 'w') as f: f.write('These are not the words you are looking for.') - self._callFUT(source, - self.dirname, - vars, - 1, False, - overwrite=True, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + overwrite=True, + template_renderer=dummy_template_renderer, + ) with open(toplevel, 'r') as f: tcontent = f.read() - self.assertNotEqual('These are not the words you are looking for.', tcontent) + self.assertNotEqual( + 'These are not the words you are looking for.', tcontent + ) with open(sub, 'r') as f: tcontent = f.read() - self.assertNotEqual('These are not the words you are looking for.', tcontent) - + self.assertNotEqual( + 'These are not the words you are looking for.', tcontent + ) + def test_detect_SkipTemplate(self): - vars = {'package':'mypackage'} + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) + def dummy_template_renderer(*args, **kwargs): from pyramid.scaffolds.copydir import SkipTemplate + raise SkipTemplate - self._callFUT(source, - self.dirname, - vars, - 1, False, - template_renderer=dummy_template_renderer) + + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + template_renderer=dummy_template_renderer, + ) def test_query_interactive(self): from pyramid.scaffolds import copydir - vars = {'package':'mypackage'} + + vars = {'package': 'mypackage'} source = pkg_resources.resource_filename(*self.fixturetuple) - self._callFUT(source, - self.dirname, - vars, - 1, False, - overwrite=False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + overwrite=False, + template_renderer=dummy_template_renderer, + ) target = os.path.join(self.dirname, 'mypackage', '__init__.py') with open(target, 'w') as f: f.write('These are not the words you are looking for.') @@ -183,35 +237,41 @@ class Test_copy_dir(unittest.TestCase): # execution of a branch original_code_object = copydir.query_interactive copydir.query_interactive = lambda *args, **kwargs: False - self._callFUT(source, - self.dirname, - vars, - 1, False, - interactive=True, - overwrite=False, - template_renderer=dummy_template_renderer) + self._callFUT( + source, + self.dirname, + vars, + 1, + False, + interactive=True, + overwrite=False, + template_renderer=dummy_template_renderer, + ) copydir.query_interactive = original_code_object -class Test_raise_SkipTemplate(unittest.TestCase): +class Test_raise_SkipTemplate(unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.scaffolds.copydir import skip_template + return skip_template(*arg, **kw) def test_raise_SkipTemplate(self): from pyramid.scaffolds.copydir import SkipTemplate - self.assertRaises(SkipTemplate, - self._callFUT, True, "exc-message") -class Test_makedirs(unittest.TestCase): + self.assertRaises(SkipTemplate, self._callFUT, True, "exc-message") + +class Test_makedirs(unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.scaffolds.copydir import makedirs + return makedirs(*arg, **kw) def test_makedirs_parent_dir(self): import shutil import tempfile + tmpdir = tempfile.mkdtemp() target = os.path.join(tmpdir, 'nonexistent_subdir') self._callFUT(target, 2, None) @@ -220,100 +280,118 @@ class Test_makedirs(unittest.TestCase): def test_makedirs_no_parent_dir(self): import shutil import tempfile + tmpdir = tempfile.mkdtemp() target = os.path.join(tmpdir, 'nonexistent_subdir', 'non2') self._callFUT(target, 2, None) shutil.rmtree(tmpdir) -class Test_support_functions(unittest.TestCase): +class Test_support_functions(unittest.TestCase): def _call_html_quote(self, *arg, **kw): from pyramid.scaffolds.copydir import html_quote + return html_quote(*arg, **kw) def _call_url_quote(self, *arg, **kw): from pyramid.scaffolds.copydir import url_quote + return url_quote(*arg, **kw) def _call_test(self, *arg, **kw): from pyramid.scaffolds.copydir import test + return test(*arg, **kw) def test_html_quote(self): import string + s = None self.assertEqual(self._call_html_quote(s), '') s = string.ascii_letters self.assertEqual(self._call_html_quote(s), s) s = "Λεμεσός" - self.assertEqual(self._call_url_quote(s), - "%CE%9B%CE%B5%CE%BC%CE%B5%CF%83%CF%8C%CF%82") + self.assertEqual( + self._call_url_quote(s), + "%CE%9B%CE%B5%CE%BC%CE%B5%CF%83%CF%8C%CF%82", + ) def test_url_quote(self): import string + s = None self.assertEqual(self._call_url_quote(s), '') s = string.ascii_letters self.assertEqual(self._call_url_quote(s), s) s = "Λεμεσός" - self.assertEqual(self._call_url_quote(s), - "%CE%9B%CE%B5%CE%BC%CE%B5%CF%83%CF%8C%CF%82") + self.assertEqual( + self._call_url_quote(s), + "%CE%9B%CE%B5%CE%BC%CE%B5%CF%83%CF%8C%CF%82", + ) def test_test(self): conf = True true_cond = "faked" - self.assertEqual(self._call_test( - conf, true_cond, false_cond=None), "faked") + self.assertEqual( + self._call_test(conf, true_cond, false_cond=None), "faked" + ) conf = False - self.assertEqual(self._call_test( - conf, true_cond, false_cond="alsofaked"), "alsofaked") + self.assertEqual( + self._call_test(conf, true_cond, false_cond="alsofaked"), + "alsofaked", + ) class Test_should_skip_file(unittest.TestCase): - def _callFUT(self, *arg, **kw): from pyramid.scaffolds.copydir import should_skip_file + return should_skip_file(*arg, **kw) def test_should_skip_dot_hidden_file(self): self.assertEqual( - self._callFUT('.a_filename'), - 'Skipping hidden file %(filename)s') + self._callFUT('.a_filename'), 'Skipping hidden file %(filename)s' + ) def test_should_skip_backup_file(self): for name in ('a_filename~', 'a_filename.bak'): self.assertEqual( - self._callFUT(name), - 'Skipping backup file %(filename)s') + self._callFUT(name), 'Skipping backup file %(filename)s' + ) def test_should_skip_bytecompiled_file(self): for name in ('afilename.pyc', 'afilename.pyo'): extension = os.path.splitext(name)[1] self.assertEqual( self._callFUT(name), - 'Skipping %s file ' % extension + '%(filename)s') + 'Skipping %s file ' % extension + '%(filename)s', + ) def test_should_skip_jython_class_file(self): self.assertEqual( self._callFUT('afilename$py.class'), - 'Skipping $py.class file %(filename)s') + 'Skipping $py.class file %(filename)s', + ) def test_should_skip_version_control_directory(self): for name in ('CVS', '_darcs'): self.assertEqual( self._callFUT(name), - 'Skipping version control directory %(filename)s') + 'Skipping version control directory %(filename)s', + ) def test_valid_file_is_not_skipped(self): - self.assertEqual( - self._callFUT('a_filename'), None) + self.assertEqual(self._callFUT('a_filename'), None) + -class RawInputMockObject( object ): +class RawInputMockObject(object): count = 0 - def __init__( self, fake_input ): - self.input= fake_input + + def __init__(self, fake_input): + self.input = fake_input self.count = 0 - def __call__( self, prompt ): + + def __call__(self, prompt): # Don't cycle endlessly. self.count += 1 if self.count > 1: @@ -321,11 +399,12 @@ class RawInputMockObject( object ): else: return self.input -class Test_query_interactive(unittest.TestCase): +class Test_query_interactive(unittest.TestCase): def setUp(self): import tempfile from pyramid.compat import NativeIO + self.dirname = tempfile.mkdtemp() self.out = NativeIO() self.fixturetuple = ('tests.test_scaffolds', 'fixture_scaffold') @@ -338,64 +417,90 @@ whom you are looking; now you have found them.""" self.src_fn = os.path.join(self.dirname, 'mypackage', '__init__.py') self.dest_fn = os.path.join(self.dirname, 'mypackage', '__init__.py') - # query_interactive is only normally executed when the destination + # query_interactive is only normally executed when the destination # is discovered to be already occupied by existing files, so ... # create the required occupancy. from pyramid.scaffolds.copydir import copy_dir - copy_dir(self.fixturetuple, - self.dirname, - {'package':'mypackage'}, - 0, False, - template_renderer=dummy_template_renderer) + + copy_dir( + self.fixturetuple, + self.dirname, + {'package': 'mypackage'}, + 0, + False, + template_renderer=dummy_template_renderer, + ) def tearDown(self): import shutil + shutil.rmtree(self.dirname, ignore_errors=True) self.out.close() def _callFUT(self, *arg, **kw): from pyramid.scaffolds.copydir import query_interactive + return query_interactive(*arg, **kw) def test_query_interactive_0y(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("y") - self._callFUT(self.src_fn, self.dest_fn, - self.src_content, self.dest_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.src_content, + self.dest_content, + simulate=False, + out_=self.out, + ) self.assertTrue("Replace" in self.out.getvalue()) def test_query_interactive_1n(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("n") - self._callFUT(self.src_fn, self.dest_fn, - self.src_content, - '\n'.join(self.dest_content.split('\n')[:-1]), - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.src_content, + '\n'.join(self.dest_content.split('\n')[:-1]), + simulate=False, + out_=self.out, + ) self.assertTrue("Replace" in self.out.getvalue()) def test_query_interactive_2b(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("b") - with open(os.path.join( - self.dirname, 'mypackage', '__init__.py.bak'), 'w') as fp: + with open( + os.path.join(self.dirname, 'mypackage', '__init__.py.bak'), 'w' + ) as fp: fp.write("") fp.close() - self._callFUT(self.src_fn, self.dest_fn, - self.dest_content, self.src_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.dest_content, + self.src_content, + simulate=False, + out_=self.out, + ) self.assertTrue("Backing up" in self.out.getvalue()) def test_query_interactive_3d(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("d") - self._callFUT(self.src_fn, self.dest_fn, - self.dest_content, self.src_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.dest_content, + self.src_content, + simulate=False, + out_=self.out, + ) output = self.out.getvalue() # The useful text in self.out gets wiped out on the second # call to raw_input, otherwise the test could be made @@ -406,11 +511,16 @@ now you have found them.""" def test_query_interactive_4dc(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("dc") - self._callFUT(self.src_fn, self.dest_fn, - self.dest_content, self.src_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.dest_content, + self.src_content, + simulate=False, + out_=self.out, + ) output = self.out.getvalue() # The useful text in self.out gets wiped out on the second # call to raw_input, otherwise, the test could be made @@ -421,11 +531,16 @@ now you have found them.""" def test_query_interactive_5allbad(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("all z") - self._callFUT(self.src_fn, self.dest_fn, - self.src_content, self.dest_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.src_content, + self.dest_content, + simulate=False, + out_=self.out, + ) output = self.out.getvalue() # The useful text in self.out gets wiped out on the second # call to raw_input, otherwise the test could be made @@ -436,11 +551,16 @@ now you have found them.""" def test_query_interactive_6all(self): from pyramid.scaffolds import copydir + copydir.input_ = RawInputMockObject("all b") - self._callFUT(self.src_fn, self.dest_fn, - self.src_content, self.dest_content, - simulate=False, - out_=self.out) + self._callFUT( + self.src_fn, + self.dest_fn, + self.src_content, + self.dest_content, + simulate=False, + out_=self.out, + ) output = self.out.getvalue() # The useful text in self.out gets wiped out on the second # call to raw_input, otherwise the test could be made @@ -449,6 +569,6 @@ now you have found them.""" # self.assertTrue("Responses" in output, output) self.assertTrue("Replace" in output) + def dummy_template_renderer(content, v, filename=None): return content - diff --git a/tests/test_scaffolds/test_init.py b/tests/test_scaffolds/test_init.py index f4d1b287a..6238915f6 100644 --- a/tests/test_scaffolds/test_init.py +++ b/tests/test_scaffolds/test_init.py @@ -1,21 +1,22 @@ import unittest + class TestPyramidTemplate(unittest.TestCase): def _makeOne(self): from pyramid.scaffolds import PyramidTemplate + return PyramidTemplate('name') def test_pre(self): inst = self._makeOne() - vars = {'package':'one'} + vars = {'package': 'one'} inst.pre('command', 'output dir', vars) self.assertTrue(vars['random_string']) self.assertEqual(vars['package_logger'], 'one') def test_pre_root(self): inst = self._makeOne() - vars = {'package':'root'} + vars = {'package': 'root'} inst.pre('command', 'output dir', vars) self.assertTrue(vars['random_string']) self.assertEqual(vars['package_logger'], 'app') - diff --git a/tests/test_scaffolds/test_template.py b/tests/test_scaffolds/test_template.py index 98f2daf73..d9a2dfadb 100644 --- a/tests/test_scaffolds/test_template.py +++ b/tests/test_scaffolds/test_template.py @@ -2,59 +2,72 @@ import unittest from pyramid.compat import bytes_ + class TestTemplate(unittest.TestCase): def _makeOne(self, name='whatever'): from pyramid.scaffolds.template import Template + return Template(name) def test_render_template_success(self): inst = self._makeOne() - result = inst.render_template('{{a}} {{b}}', {'a':'1', 'b':'2'}) + result = inst.render_template('{{a}} {{b}}', {'a': '1', 'b': '2'}) self.assertEqual(result, bytes_('1 2')) def test_render_template_expr_failure(self): inst = self._makeOne() - self.assertRaises(AttributeError, inst.render_template, - '{{a.foo}}', {'a':'1', 'b':'2'}) + self.assertRaises( + AttributeError, + inst.render_template, + '{{a.foo}}', + {'a': '1', 'b': '2'}, + ) def test_render_template_expr_success(self): inst = self._makeOne() - result = inst.render_template('{{a.lower()}}', {'a':'A'}) + result = inst.render_template('{{a.lower()}}', {'a': 'A'}) self.assertEqual(result, b'a') def test_render_template_expr_success_via_pipe(self): inst = self._makeOne() - result = inst.render_template('{{b|c|a.lower()}}', {'a':'A'}) + result = inst.render_template('{{b|c|a.lower()}}', {'a': 'A'}) self.assertEqual(result, b'a') def test_render_template_expr_success_via_pipe2(self): inst = self._makeOne() - result = inst.render_template('{{b|a.lower()|c}}', {'a':'A'}) + result = inst.render_template('{{b|a.lower()|c}}', {'a': 'A'}) self.assertEqual(result, b'a') def test_render_template_expr_value_is_None(self): inst = self._makeOne() - result = inst.render_template('{{a}}', {'a':None}) + result = inst.render_template('{{a}}', {'a': None}) self.assertEqual(result, b'') def test_render_template_with_escaped_double_braces(self): inst = self._makeOne() - result = inst.render_template('{{a}} {{b}} \{\{a\}\} \{\{c\}\}', {'a':'1', 'b':'2'}) + result = inst.render_template( + '{{a}} {{b}} \{\{a\}\} \{\{c\}\}', {'a': '1', 'b': '2'} + ) self.assertEqual(result, bytes_('1 2 {{a}} {{c}}')) def test_render_template_with_breaking_escaped_braces(self): inst = self._makeOne() - result = inst.render_template('{{a}} {{b}} \{\{a\} \{b\}\}', {'a':'1', 'b':'2'}) + result = inst.render_template( + '{{a}} {{b}} \{\{a\} \{b\}\}', {'a': '1', 'b': '2'} + ) self.assertEqual(result, bytes_('1 2 \{\{a\} \{b\}\}')) def test_render_template_with_escaped_single_braces(self): inst = self._makeOne() - result = inst.render_template('{{a}} {{b}} \{a\} \{b', {'a':'1', 'b':'2'}) + result = inst.render_template( + '{{a}} {{b}} \{a\} \{b', {'a': '1', 'b': '2'} + ) self.assertEqual(result, bytes_('1 2 \{a\} \{b')) def test_module_dir(self): import sys import pkg_resources + package = sys.modules['pyramid.scaffolds.template'] path = pkg_resources.resource_filename(package.__name__, '') inst = self._makeOne() @@ -74,10 +87,11 @@ class TestTemplate(unittest.TestCase): import os import sys import pkg_resources + package = sys.modules['pyramid.scaffolds.template'] path = pkg_resources.resource_filename(package.__name__, '') inst = self._makeOne() - inst._template_dir ='foo' + inst._template_dir = 'foo' result = inst.template_dir() self.assertEqual(result, os.path.join(path, 'foo')) @@ -85,6 +99,7 @@ class TestTemplate(unittest.TestCase): import os import sys import pkg_resources + package = sys.modules['pyramid.scaffolds.template'] path = pkg_resources.resource_filename(package.__name__, '') inst = self._makeOne() @@ -93,18 +108,21 @@ class TestTemplate(unittest.TestCase): copydir = DummyCopydir() inst.copydir = copydir command = DummyCommand() - inst.write_files(command, 'output dir', {'a':1}) + inst.write_files(command, 'output dir', {'a': 1}) self.assertEqual(copydir.template_dir, os.path.join(path, 'foo')) self.assertEqual(copydir.output_dir, 'output dir') - self.assertEqual(copydir.vars, {'a':1}) - self.assertEqual(copydir.kw, - {'template_renderer':inst.render_template, - 'indent':1, - 'verbosity':1, - 'simulate':False, - 'overwrite':False, - 'interactive':False, - }) + self.assertEqual(copydir.vars, {'a': 1}) + self.assertEqual( + copydir.kw, + { + 'template_renderer': inst.render_template, + 'indent': 1, + 'verbosity': 1, + 'simulate': False, + 'overwrite': False, + 'interactive': False, + }, + ) def test_write_files_path_missing(self): L = [] @@ -116,7 +134,7 @@ class TestTemplate(unittest.TestCase): copydir = DummyCopydir() inst.copydir = copydir command = DummyCommand() - inst.write_files(command, 'output dir', {'a':1}) + inst.write_files(command, 'output dir', {'a': 1}) self.assertEqual(L, ['output dir']) def test_run(self): @@ -129,13 +147,14 @@ class TestTemplate(unittest.TestCase): copydir = DummyCopydir() inst.copydir = copydir command = DummyCommand() - inst.run(command, 'output dir', {'a':1}) + inst.run(command, 'output dir', {'a': 1}) self.assertEqual(L, ['output dir']) def test_check_vars(self): inst = self._makeOne() self.assertRaises(RuntimeError, inst.check_vars, 'one', 'two') + class DummyCopydir(object): def copy_dir(self, template_dir, output_dir, vars, **kw): self.template_dir = template_dir @@ -143,13 +162,13 @@ class DummyCopydir(object): self.vars = vars self.kw = kw + class DummyArgs(object): simulate = False overwrite = False interactive = False + class DummyCommand(object): args = DummyArgs() verbosity = 1 - - diff --git a/tests/test_scripting.py b/tests/test_scripting.py index ed88bb470..6bb293a0d 100644 --- a/tests/test_scripting.py +++ b/tests/test_scripting.py @@ -1,8 +1,10 @@ import unittest + class Test_get_root(unittest.TestCase): def _callFUT(self, app, request=None): from pyramid.scripting import get_root + return get_root(app, request) def _makeRegistry(self): @@ -10,6 +12,7 @@ class Test_get_root(unittest.TestCase): def setUp(self): from pyramid.threadlocal import manager + self.manager = manager self.default = manager.get() @@ -38,9 +41,11 @@ class Test_get_root(unittest.TestCase): closer() self.assertEqual(self.default, self.manager.get()) + class Test_prepare(unittest.TestCase): def _callFUT(self, request=None, registry=None): from pyramid.scripting import prepare + return prepare(request, registry) def _makeRegistry(self, L=None): @@ -50,11 +55,13 @@ class Test_prepare(unittest.TestCase): def setUp(self): from pyramid.threadlocal import manager + self.manager = manager self.default = manager.get() def test_it_no_valid_apps(self): from pyramid.exceptions import ConfigurationError + self.assertRaises(ConfigurationError, self._callFUT) def test_it_norequest(self): @@ -120,6 +127,7 @@ class Test_prepare(unittest.TestCase): def test_it_with_extensions(self): from pyramid.util import InstancePropertyHelper + exts = DummyExtensions() ext_method = lambda r: 'bar' name, fn = InstancePropertyHelper.make_property(ext_method, 'foo') @@ -143,18 +151,22 @@ class Test_prepare(unittest.TestCase): self.assertEqual(pushed['request'].registry, registry) self.assertEqual(root.a, (request,)) orig_closer = info['closer'] + def closer(): orig_closer() closer_called[0] = True + info['closer'] = closer self.assertTrue(closer_called[0]) self.assertEqual(self.default, self.manager.get()) self.assertEqual(request.context, root) self.assertEqual(request.registry, registry) + class Test__make_request(unittest.TestCase): def _callFUT(self, path='/', registry=None): from pyramid.scripting import _make_request + return _make_request(path, registry) def _makeRegistry(self): @@ -168,6 +180,7 @@ class Test__make_request(unittest.TestCase): def test_it_with_no_registry(self): from pyramid.config import global_registries + registry = self._makeRegistry() global_registries.add(registry) try: @@ -177,11 +190,14 @@ class Test__make_request(unittest.TestCase): finally: global_registries.empty() + class Dummy: pass + dummy_root = Dummy() + class DummyFactory(object): @classmethod def blank(cls, path): @@ -192,15 +208,17 @@ class DummyFactory(object): self.a = a self.kw = kw + class DummyRegistry(object): def __init__(self, utilities): self.utilities = utilities - def queryUtility(self, iface, default=None): # pragma: no cover + def queryUtility(self, iface, default=None): # pragma: no cover if self.utilities: return self.utilities.pop(0) return default + class DummyApp: def __init__(self, registry=None): if registry: @@ -209,12 +227,15 @@ class DummyApp: def root_factory(self, environ): return dummy_root + class DummyRequest(object): matchdict = None matched_route = None + def __init__(self, environ): self.environ = environ + class DummyExtensions: def __init__(self): self.descriptors = {} diff --git a/tests/test_scripts/dummy.py b/tests/test_scripts/dummy.py index f1ef403f8..69e69a280 100644 --- a/tests/test_scripts/dummy.py +++ b/tests/test_scripts/dummy.py @@ -3,21 +3,28 @@ class DummyTweens(object): self._implicit = implicit self.explicit = explicit self.name_to_alias = {} + def implicit(self): return self._implicit + class Dummy: pass + dummy_root = Dummy() + class DummyRegistry(object): settings = {} + def queryUtility(self, iface, default=None, name=''): return default + dummy_registry = DummyRegistry() + class DummyShell(object): env = {} help = '' @@ -30,15 +37,18 @@ class DummyShell(object): self.called = True self.env['request'].dummy_attr = self.dummy_attr + class DummyInteractor: def __call__(self, banner, local): self.banner = banner self.local = local + class DummyApp: def __init__(self): self.registry = dummy_registry + class DummyMapper(object): def __init__(self, *routes): self.routes = routes @@ -46,9 +56,11 @@ class DummyMapper(object): def get_routes(self, include_static=False): return self.routes + class DummyRoute(object): - def __init__(self, name, pattern, factory=None, - matchdict=None, predicate=None): + def __init__( + self, name, pattern, factory=None, matchdict=None, predicate=None + ): self.name = name self.path = pattern self.pattern = pattern @@ -61,35 +73,50 @@ class DummyRoute(object): def match(self, route): return self.matchdict + class DummyRequest: application_url = 'http://example.com:5432' script_name = '' + def __init__(self, environ): self.environ = environ self.matchdict = {} + class DummyView(object): def __init__(self, **attrs): self.__request_attrs__ = attrs - def view(context, request): pass + def view(context, request): + pass + from zope.interface import implementer from pyramid.interfaces import IMultiView + + @implementer(IMultiView) class DummyMultiView(object): - def __init__(self, *views, **attrs): self.views = [(None, view, None) for view in views] self.__request_attrs__ = attrs + class DummyCloser(object): def __call__(self): self.called = True + class DummyBootstrap(object): - def __init__(self, app=None, registry=None, request=None, root=None, - root_factory=None, closer=None): + def __init__( + self, + app=None, + registry=None, + request=None, + root=None, + root_factory=None, + closer=None, + ): self.app = app or DummyApp() if registry is None: registry = DummyRegistry() @@ -150,7 +177,9 @@ class dummy_setup_logging(object): class DummyLoader(object): - def __init__(self, settings=None, app_settings=None, app=None, server=None): + def __init__( + self, settings=None, app_settings=None, app=None, server=None + ): if not settings: settings = {} if not app_settings: @@ -163,6 +192,7 @@ class DummyLoader(object): def __call__(self, uri): import plaster + self.uri = plaster.parse_uri(uri) return self diff --git a/tests/test_scripts/test_common.py b/tests/test_scripts/test_common.py index 60741db92..e286d3c3e 100644 --- a/tests/test_scripts/test_common.py +++ b/tests/test_scripts/test_common.py @@ -1,13 +1,16 @@ import unittest + class TestParseVars(unittest.TestCase): def test_parse_vars_good(self): from pyramid.scripts.common import parse_vars + vars = ['a=1', 'b=2'] result = parse_vars(vars) self.assertEqual(result, {'a': '1', 'b': '2'}) def test_parse_vars_bad(self): from pyramid.scripts.common import parse_vars + vars = ['a'] self.assertRaises(ValueError, parse_vars, vars) diff --git a/tests/test_scripts/test_pcreate.py b/tests/test_scripts/test_pcreate.py index 0286614ce..6ac082b41 100644 --- a/tests/test_scripts/test_pcreate.py +++ b/tests/test_scripts/test_pcreate.py @@ -4,6 +4,7 @@ import unittest class TestPCreateCommand(unittest.TestCase): def setUp(self): from pyramid.compat import NativeIO + self.out_ = NativeIO() def out(self, msg): @@ -11,6 +12,7 @@ class TestPCreateCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.pcreate import PCreateCommand + return PCreateCommand def _makeOne(self, *args, **kw): @@ -46,8 +48,9 @@ class TestPCreateCommand(unittest.TestCase): result = cmd.run() self.assertEqual(result, 2) out = self.out_.getvalue() - self.assertTrue(out.count( - 'You must provide at least one scaffold name')) + self.assertTrue( + out.count('You must provide at least one scaffold name') + ) def test_no_project_name(self): cmd = self._makeOne('-s', 'dummy') @@ -65,6 +68,7 @@ class TestPCreateCommand(unittest.TestCase): def test_known_scaffold_single_rendered(self): import os + cmd = self._makeOne('-s', 'dummy', 'Distro') scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] @@ -73,17 +77,25 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro')), + ) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_scaffold_with_package_name(self): import os - cmd = self._makeOne('-s', 'dummy', '--package-name', 'dummy_package', - 'Distro') + + cmd = self._makeOne( + '-s', 'dummy', '--package-name', 'dummy_package', 'Distro' + ) scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] cmd.pyramid_dist = DummyDist("0.1") @@ -92,17 +104,22 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro')), + ) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'dummy_package', - 'package': 'dummy_package', 'pyramid_version': '0.1', - 'pyramid_docs_branch':'0.1-branch'}) - + { + 'project': 'Distro', + 'egg': 'dummy_package', + 'package': 'dummy_package', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_scaffold_with_hyphen_in_project_name(self): import os + cmd = self._makeOne('-s', 'dummy', 'Distro-') scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] @@ -111,15 +128,22 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro-')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro-')), + ) self.assertEqual( scaffold.vars, - {'project': 'Distro-', 'egg': 'Distro_', 'package': 'distro_', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) + { + 'project': 'Distro-', + 'egg': 'Distro_', + 'package': 'distro_', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_known_scaffold_absolute_path(self): import os + path = os.path.abspath('Distro') cmd = self._makeOne('-s', 'dummy', path) cmd.pyramid_dist = DummyDist("0.1") @@ -130,15 +154,22 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro')), + ) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_known_scaffold_multiple_rendered(self): import os + cmd = self._makeOne('-s', 'dummy1', '-s', 'dummy2', 'Distro') scaffold1 = DummyScaffold('dummy1') scaffold2 = DummyScaffold('dummy2') @@ -148,23 +179,36 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold1.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro')), + ) self.assertEqual( scaffold1.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) self.assertEqual( scaffold2.output_dir, - os.path.normpath(os.path.join(os.getcwd(), 'Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), 'Distro')), + ) self.assertEqual( scaffold2.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_known_scaffold_with_path_as_project_target_rendered(self): import os + cmd = self._makeOne('-s', 'dummy', '/tmp/foo/Distro/') scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] @@ -173,13 +217,18 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.output_dir, - os.path.normpath(os.path.join(os.getcwd(), '/tmp/foo/Distro')) - ) + os.path.normpath(os.path.join(os.getcwd(), '/tmp/foo/Distro')), + ) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.1', 'pyramid_docs_branch':'0.1-branch'}) - + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.1', + 'pyramid_docs_branch': '0.1-branch', + }, + ) def test_scaffold_with_prod_pyramid_version(self): cmd = self._makeOne('-s', 'dummy', 'Distro') @@ -190,8 +239,14 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.2', 'pyramid_docs_branch':'0.2-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.2', + 'pyramid_docs_branch': '0.2-branch', + }, + ) def test_scaffold_with_prod_pyramid_long_version(self): cmd = self._makeOne('-s', 'dummy', 'Distro') @@ -202,8 +257,14 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.2.1', 'pyramid_docs_branch':'0.2-branch'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.2.1', + 'pyramid_docs_branch': '0.2-branch', + }, + ) def test_scaffold_with_prod_pyramid_unparsable_version(self): cmd = self._makeOne('-s', 'dummy', 'Distro') @@ -214,8 +275,14 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': 'abc', 'pyramid_docs_branch':'latest'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': 'abc', + 'pyramid_docs_branch': 'latest', + }, + ) def test_scaffold_with_dev_pyramid_version(self): cmd = self._makeOne('-s', 'dummy', 'Distro') @@ -226,9 +293,14 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.12dev', - 'pyramid_docs_branch': 'master'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.12dev', + 'pyramid_docs_branch': 'master', + }, + ) def test_scaffold_with_dev_pyramid_long_version(self): cmd = self._makeOne('-s', 'dummy', 'Distro') @@ -239,16 +311,25 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Distro', 'egg': 'Distro', 'package': 'distro', - 'pyramid_version': '0.10.1dev', - 'pyramid_docs_branch': 'master'}) + { + 'project': 'Distro', + 'egg': 'Distro', + 'package': 'distro', + 'pyramid_version': '0.10.1dev', + 'pyramid_docs_branch': 'master', + }, + ) def test_confirm_override_conflicting_name(self): from pyramid.scripts.pcreate import PCreateCommand + class YahInputPCreateCommand(PCreateCommand): def confirm_bad_name(self, pkg_name): return True - cmd = self._makeOne('-s', 'dummy', 'Unittest', target_class=YahInputPCreateCommand) + + cmd = self._makeOne( + '-s', 'dummy', 'Unittest', target_class=YahInputPCreateCommand + ) scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] cmd.pyramid_dist = DummyDist("0.10.1dev") @@ -256,12 +337,19 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Unittest', 'egg': 'Unittest', 'package': 'unittest', - 'pyramid_version': '0.10.1dev', - 'pyramid_docs_branch': 'master'}) + { + 'project': 'Unittest', + 'egg': 'Unittest', + 'package': 'unittest', + 'pyramid_version': '0.10.1dev', + 'pyramid_docs_branch': 'master', + }, + ) def test_force_override_conflicting_name(self): - cmd = self._makeOne('-s', 'dummy', 'Unittest', '--ignore-conflicting-name') + cmd = self._makeOne( + '-s', 'dummy', 'Unittest', '--ignore-conflicting-name' + ) scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] cmd.pyramid_dist = DummyDist("0.10.1dev") @@ -269,16 +357,25 @@ class TestPCreateCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual( scaffold.vars, - {'project': 'Unittest', 'egg': 'Unittest', 'package': 'unittest', - 'pyramid_version': '0.10.1dev', - 'pyramid_docs_branch': 'master'}) + { + 'project': 'Unittest', + 'egg': 'Unittest', + 'package': 'unittest', + 'pyramid_version': '0.10.1dev', + 'pyramid_docs_branch': 'master', + }, + ) def test_force_override_site_name(self): from pyramid.scripts.pcreate import PCreateCommand + class NayInputPCreateCommand(PCreateCommand): def confirm_bad_name(self, pkg_name): return False - cmd = self._makeOne('-s', 'dummy', 'Site', target_class=NayInputPCreateCommand) + + cmd = self._makeOne( + '-s', 'dummy', 'Site', target_class=NayInputPCreateCommand + ) scaffold = DummyScaffold('dummy') cmd.scaffolds = [scaffold] cmd.pyramid_dist = DummyDist("0.10.1dev") @@ -289,12 +386,14 @@ class TestPCreateCommand(unittest.TestCase): class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.pcreate import main + return main(argv, quiet=True) def test_it(self): result = self._callFUT(['pcreate']) self.assertEqual(result, 2) + class DummyScaffold(object): def __init__(self, name): self.name = name @@ -304,6 +403,7 @@ class DummyScaffold(object): self.output_dir = output_dir self.vars = vars + class DummyDist(object): def __init__(self, version): self.version = version diff --git a/tests/test_scripts/test_pdistreport.py b/tests/test_scripts/test_pdistreport.py index e229667c5..031a6ff2b 100644 --- a/tests/test_scripts/test_pdistreport.py +++ b/tests/test_scripts/test_pdistreport.py @@ -1,57 +1,68 @@ import unittest + class TestPDistReportCommand(unittest.TestCase): def _callFUT(self, **kw): argv = [] from pyramid.scripts.pdistreport import main + return main(argv, **kw) def test_no_dists(self): def platform(): return 'myplatform' + pkg_resources = DummyPkgResources() L = [] + def out(*args): L.extend(args) - result = self._callFUT(pkg_resources=pkg_resources, platform=platform, - out=out) + + result = self._callFUT( + pkg_resources=pkg_resources, platform=platform, out=out + ) self.assertEqual(result, None) self.assertEqual( L, - ['Pyramid version:', '1', - 'Platform:', 'myplatform', - 'Packages:'] - ) + ['Pyramid version:', '1', 'Platform:', 'myplatform', 'Packages:'], + ) def test_with_dists(self): def platform(): return 'myplatform' + working_set = (DummyDistribution('abc'), DummyDistribution('def')) pkg_resources = DummyPkgResources(working_set) L = [] + def out(*args): L.extend(args) - result = self._callFUT(pkg_resources=pkg_resources, platform=platform, - out=out) + + result = self._callFUT( + pkg_resources=pkg_resources, platform=platform, out=out + ) self.assertEqual(result, None) self.assertEqual( L, - ['Pyramid version:', - '1', - 'Platform:', - 'myplatform', - 'Packages:', - ' ', - 'abc', - '1', - ' ', - '/projects/abc', - ' ', - 'def', - '1', - ' ', - '/projects/def'] - ) + [ + 'Pyramid version:', + '1', + 'Platform:', + 'myplatform', + 'Packages:', + ' ', + 'abc', + '1', + ' ', + '/projects/abc', + ' ', + 'def', + '1', + ' ', + '/projects/def', + ], + ) + class DummyPkgResources(object): def __init__(self, working_set=()): @@ -60,14 +71,14 @@ class DummyPkgResources(object): def get_distribution(self, name): return Version('1') + class Version(object): def __init__(self, version): self.version = version + class DummyDistribution(object): def __init__(self, name): self.project_name = name self.version = '1' self.location = '/projects/%s' % name - - diff --git a/tests/test_scripts/test_prequest.py b/tests/test_scripts/test_prequest.py index f7e656995..1521172bc 100644 --- a/tests/test_scripts/test_prequest.py +++ b/tests/test_scripts/test_prequest.py @@ -1,9 +1,11 @@ import unittest from . import dummy + class TestPRequestCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.prequest import PRequestCommand + return PRequestCommand def _makeOne(self, argv, headers=None): @@ -14,6 +16,7 @@ class TestPRequestCommand(unittest.TestCase): self._path_info = environ['PATH_INFO'] start_request('200 OK', headers or []) return [b'abc'] + self.loader = dummy.DummyLoader(app=helloworld) self._out = [] cmd._get_config_loader = self.loader @@ -26,11 +29,15 @@ class TestPRequestCommand(unittest.TestCase): def test_command_not_enough_args(self): command = self._makeOne([]) command.run() - self.assertEqual(self._out, ['You must provide at least two arguments']) + self.assertEqual( + self._out, ['You must provide at least two arguments'] + ) def test_command_two_args(self): - command = self._makeOne(['', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + command = self._makeOne( + ['', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._path_info, '/') self.assertEqual(self.loader.uri.path, 'development.ini') @@ -40,26 +47,31 @@ class TestPRequestCommand(unittest.TestCase): self.assertEqual(self._out, ['abc']) def test_command_path_doesnt_start_with_slash(self): - command = self._makeOne(['', 'development.ini', 'abc'], - [('Content-Type', 'text/html; charset=UTF-8')]) + command = self._makeOne( + ['', 'development.ini', 'abc'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._path_info, '/abc') self.assertEqual(self.loader.uri.path, 'development.ini') self.assertEqual(self._out, ['abc']) def test_command_has_bad_config_header(self): - command = self._makeOne( - ['', '--header=name','development.ini', '/']) + command = self._makeOne(['', '--header=name', 'development.ini', '/']) command.run() self.assertEqual( self._out[0], - ("Bad --header=name option, value must be in the form " - "'name:value'")) + ( + "Bad --header=name option, value must be in the form " + "'name:value'" + ), + ) def test_command_has_good_header_var(self): command = self._makeOne( - ['', '--header=name:value','development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + ['', '--header=name:value', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['HTTP_NAME'], 'value') self.assertEqual(self._path_info, '/') @@ -67,20 +79,28 @@ class TestPRequestCommand(unittest.TestCase): def test_command_w_basic_auth(self): command = self._makeOne( - ['', '--login=user:password', - '--header=name:value','development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + [ + '', + '--login=user:password', + '--header=name:value', + 'development.ini', + '/', + ], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['HTTP_NAME'], 'value') - self.assertEqual(self._environ['HTTP_AUTHORIZATION'], - 'Basic dXNlcjpwYXNzd29yZA==') + self.assertEqual( + self._environ['HTTP_AUTHORIZATION'], 'Basic dXNlcjpwYXNzd29yZA==' + ) self.assertEqual(self._path_info, '/') self.assertEqual(self._out, ['abc']) def test_command_has_content_type_header_var(self): command = self._makeOne( - ['', '--header=content-type:app/foo','development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + ['', '--header=content-type:app/foo', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['CONTENT_TYPE'], 'app/foo') self.assertEqual(self._path_info, '/') @@ -88,13 +108,15 @@ class TestPRequestCommand(unittest.TestCase): def test_command_has_multiple_header_vars(self): command = self._makeOne( - ['', - '--header=name:value', - '--header=name2:value2', - 'development.ini', - '/'], - [('Content-Type', 'text/html; charset=UTF-8')] - ) + [ + '', + '--header=name:value', + '--header=name2:value2', + 'development.ini', + '/', + ], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['HTTP_NAME'], 'value') self.assertEqual(self._environ['HTTP_NAME2'], 'value2') @@ -102,8 +124,10 @@ class TestPRequestCommand(unittest.TestCase): self.assertEqual(self._out, ['abc']) def test_command_method_get(self): - command = self._makeOne(['', '--method=GET', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + command = self._makeOne( + ['', '--method=GET', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['REQUEST_METHOD'], 'GET') self.assertEqual(self._path_info, '/') @@ -111,8 +135,11 @@ class TestPRequestCommand(unittest.TestCase): def test_command_method_post(self): from pyramid.compat import NativeIO - command = self._makeOne(['', '--method=POST', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + + command = self._makeOne( + ['', '--method=POST', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) stdin = NativeIO() command.stdin = stdin command.run() @@ -124,8 +151,11 @@ class TestPRequestCommand(unittest.TestCase): def test_command_method_put(self): from pyramid.compat import NativeIO - command = self._makeOne(['', '--method=PUT', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + + command = self._makeOne( + ['', '--method=PUT', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) stdin = NativeIO() command.stdin = stdin command.run() @@ -137,8 +167,11 @@ class TestPRequestCommand(unittest.TestCase): def test_command_method_patch(self): from pyramid.compat import NativeIO - command = self._makeOne(['', '--method=PATCH', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + + command = self._makeOne( + ['', '--method=PATCH', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) stdin = NativeIO() command.stdin = stdin command.run() @@ -150,9 +183,11 @@ class TestPRequestCommand(unittest.TestCase): def test_command_method_propfind(self): from pyramid.compat import NativeIO - command = self._makeOne(['', '--method=PROPFIND', 'development.ini', - '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + + command = self._makeOne( + ['', '--method=PROPFIND', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) stdin = NativeIO() command.stdin = stdin command.run() @@ -162,9 +197,11 @@ class TestPRequestCommand(unittest.TestCase): def test_command_method_options(self): from pyramid.compat import NativeIO - command = self._makeOne(['', '--method=OPTIONS', 'development.ini', - '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + + command = self._makeOne( + ['', '--method=OPTIONS', 'development.ini', '/'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) stdin = NativeIO() command.stdin = stdin command.run() @@ -173,8 +210,10 @@ class TestPRequestCommand(unittest.TestCase): self.assertEqual(self._out, ['abc']) def test_command_with_query_string(self): - command = self._makeOne(['', 'development.ini', '/abc?a=1&b=2&c'], - [('Content-Type', 'text/html; charset=UTF-8')]) + command = self._makeOne( + ['', 'development.ini', '/abc?a=1&b=2&c'], + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._environ['QUERY_STRING'], 'a=1&b=2&c') self.assertEqual(self._path_info, '/abc') @@ -183,16 +222,20 @@ class TestPRequestCommand(unittest.TestCase): def test_command_display_headers(self): command = self._makeOne( ['', '--display-headers', 'development.ini', '/'], - [('Content-Type', 'text/html; charset=UTF-8')]) + [('Content-Type', 'text/html; charset=UTF-8')], + ) command.run() self.assertEqual(self._path_info, '/') self.assertEqual( self._out, - ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc']) + ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc'], + ) def test_command_response_has_no_charset(self): - command = self._makeOne(['', '--method=GET', 'development.ini', '/'], - headers=[('Content-Type', 'image/jpeg')]) + command = self._makeOne( + ['', '--method=GET', 'development.ini', '/'], + headers=[('Content-Type', 'image/jpeg')], + ) command.run() self.assertEqual(self._path_info, '/') @@ -207,6 +250,7 @@ class TestPRequestCommand(unittest.TestCase): class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.prequest import main + return main(argv, True) def test_it(self): diff --git a/tests/test_scripts/test_proutes.py b/tests/test_scripts/test_proutes.py index 0de331c94..5bbfa9f25 100644 --- a/tests/test_scripts/test_proutes.py +++ b/tests/test_scripts/test_proutes.py @@ -15,6 +15,7 @@ class DummyIntrospector(object): class TestPRoutesCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.proutes import PRoutesCommand + return PRoutesCommand def _makeOne(self): @@ -27,12 +28,14 @@ class TestPRoutesCommand(unittest.TestCase): def _makeRegistry(self): from pyramid.registry import Registry + registry = Registry() registry.introspector = DummyIntrospector() return registry def _makeConfig(self, *arg, **kw): from pyramid.config import Configurator + config = Configurator(*arg, **kw) return config @@ -76,7 +79,7 @@ class TestPRoutesCommand(unittest.TestCase): def test_no_mapper(self): command = self._makeOne() - command._get_mapper = lambda *arg:None + command._get_mapper = lambda *arg: None L = [] command.out = L.append result = command.run() @@ -115,11 +118,15 @@ class TestPRoutesCommand(unittest.TestCase): def test_single_route_no_views_registered(self): from zope.interface import Interface from pyramid.interfaces import IRouteRequest + registry = self._makeRegistry() - def view():pass + def view(): + pass + class IMyRoute(Interface): pass + registry.registerUtility(IMyRoute, IRouteRequest, name='a') command = self._makeOne() route = dummy.DummyRoute('a', '/a') @@ -138,14 +145,18 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView + registry = self._makeRegistry() - def view():pass + def view(): + pass + class IMyRoute(Interface): pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, Interface), - IView, '') + + registry.registerAdapter( + view, (IViewClassifier, IMyRoute, Interface), IView, '' + ) registry.registerUtility(IMyRoute, IRouteRequest, name='a') command = self._makeOne() route = dummy.DummyRoute('a', '/a') @@ -159,8 +170,7 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split()[:3] self.assertEqual( - compare_to, - ['a', '/a', 'tests.test_scripts.test_proutes.view'] + compare_to, ['a', '/a', 'tests.test_scripts.test_proutes.view'] ) def test_one_route_with_long_name_one_view_registered(self): @@ -168,26 +178,26 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView + registry = self._makeRegistry() - def view():pass + def view(): + pass class IMyRoute(Interface): pass registry.registerAdapter( - view, - (IViewClassifier, IMyRoute, Interface), - IView, '' + view, (IViewClassifier, IMyRoute, Interface), IView, '' ) - registry.registerUtility(IMyRoute, IRouteRequest, - name='very_long_name_123') + registry.registerUtility( + IMyRoute, IRouteRequest, name='very_long_name_123' + ) command = self._makeOne() route = dummy.DummyRoute( - 'very_long_name_123', - '/and_very_long_pattern_as_well' + 'very_long_name_123', '/and_very_long_pattern_as_well' ) mapper = dummy.DummyMapper(route) command._get_mapper = lambda *arg: mapper @@ -200,9 +210,11 @@ class TestPRoutesCommand(unittest.TestCase): compare_to = L[-1].split()[:3] self.assertEqual( compare_to, - ['very_long_name_123', - '/and_very_long_pattern_as_well', - 'tests.test_scripts.test_proutes.view'] + [ + 'very_long_name_123', + '/and_very_long_pattern_as_well', + 'tests.test_scripts.test_proutes.view', + ], ) def test_class_view(self): @@ -215,7 +227,7 @@ class TestPRoutesCommand(unittest.TestCase): view=dummy.DummyView, attr='view', renderer=nr, - request_method='POST' + request_method='POST', ) command = self._makeOne() @@ -227,8 +239,10 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', - 'tests.test_scripts.dummy.DummyView.view', 'POST' + 'foo', + '/a/b', + 'tests.test_scripts.dummy.DummyView.view', + 'POST', ] self.assertEqual(compare_to, expected) @@ -237,19 +251,27 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView + registry = self._makeRegistry() - def view():pass + def view(): + pass + class IMyRoot(Interface): pass + class IMyRoute(Interface): pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, IMyRoot), - IView, '') + + registry.registerAdapter( + view, (IViewClassifier, IMyRoute, IMyRoot), IView, '' + ) registry.registerUtility(IMyRoute, IRouteRequest, name='a') command = self._makeOne() - def factory(request): pass + + def factory(request): + pass + route = dummy.DummyRoute('a', '/a', factory=factory) mapper = dummy.DummyMapper(route) command._get_mapper = lambda *arg: mapper @@ -269,20 +291,18 @@ class TestPRoutesCommand(unittest.TestCase): registry = self._makeRegistry() - def view(): pass + def view(): + pass class IMyRoute(Interface): pass multiview1 = dummy.DummyMultiView( - view, context='context', - view_name='a1' + view, context='context', view_name='a1' ) registry.registerAdapter( - multiview1, - (IViewClassifier, IMyRoute, Interface), - IMultiView, '' + multiview1, (IViewClassifier, IMyRoute, Interface), IMultiView, '' ) registry.registerUtility(IMyRoute, IRouteRequest, name='a') command = self._makeOne() @@ -300,13 +320,11 @@ class TestPRoutesCommand(unittest.TestCase): view_str = '<tests.test_scripts.dummy.DummyMultiView' final = '%s.%s' % (view_module, view_str) - self.assertEqual( - compare_to, - ['a', '/a', final] - ) + self.assertEqual(compare_to, ['a', '/a', final]) def test__get_mapper(self): from pyramid.urldispatch import RoutesMapper + command = self._makeOne() registry = self._makeRegistry() @@ -316,15 +334,13 @@ class TestPRoutesCommand(unittest.TestCase): def test_one_route_all_methods_view_only_post(self): from pyramid.renderers import null_renderer as nr - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') config.add_view( - route_name='foo', - view=view1, - renderer=nr, - request_method='POST' + route_name='foo', view=view1, renderer=nr, request_method='POST' ) command = self._makeOne() @@ -336,23 +352,22 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', - 'tests.test_scripts.test_proutes.view1', 'POST' + 'foo', + '/a/b', + 'tests.test_scripts.test_proutes.view1', + 'POST', ] self.assertEqual(compare_to, expected) def test_one_route_only_post_view_all_methods(self): from pyramid.renderers import null_renderer as nr - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='POST') - config.add_view( - route_name='foo', - view=view1, - renderer=nr, - ) + config.add_view(route_name='foo', view=view1, renderer=nr) command = self._makeOne() L = [] @@ -363,15 +378,18 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', - 'tests.test_scripts.test_proutes.view1', 'POST' + 'foo', + '/a/b', + 'tests.test_scripts.test_proutes.view1', + 'POST', ] self.assertEqual(compare_to, expected) def test_one_route_only_post_view_post_and_get(self): from pyramid.renderers import null_renderer as nr - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='POST') @@ -379,7 +397,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=('POST', 'GET') + request_method=('POST', 'GET'), ) command = self._makeOne() @@ -391,23 +409,23 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', - 'tests.test_scripts.test_proutes.view1', 'POST' + 'foo', + '/a/b', + 'tests.test_scripts.test_proutes.view1', + 'POST', ] self.assertEqual(compare_to, expected) def test_route_request_method_mismatch(self): from pyramid.renderers import null_renderer as nr - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='POST') config.add_view( - route_name='foo', - view=view1, - renderer=nr, - request_method='GET' + route_name='foo', view=view1, renderer=nr, request_method='GET' ) command = self._makeOne() @@ -419,21 +437,24 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', + 'foo', + '/a/b', 'tests.test_scripts.test_proutes.view1', - '<route', 'mismatch>' + '<route', + 'mismatch>', ] self.assertEqual(compare_to, expected) def test_route_static_views(self): from pyramid.renderers import null_renderer as nr + config = self._makeConfig(autocommit=True) config.add_static_view('static', 'static', cache_max_age=3600) path2 = os.path.normpath('/var/www/static') config.add_static_view(name='static2', path=path2) config.add_static_view( name='pyramid_scaffold', - path='pyramid:scaffolds/starter/+package+/static' + path='pyramid:scaffolds/starter/+package+/static', ) command = self._makeOne() @@ -445,11 +466,19 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 5) expected = [ - ['__static/', '/static/*subpath', - 'tests.test_scripts:static/', '*'], + [ + '__static/', + '/static/*subpath', + 'tests.test_scripts:static/', + '*', + ], ['__static2/', '/static2/*subpath', path2 + os.sep, '*'], - ['__pyramid_scaffold/', '/pyramid_scaffold/*subpath', - 'pyramid:scaffolds/starter/+package+/static/', '*'], + [ + '__pyramid_scaffold/', + '/pyramid_scaffold/*subpath', + 'pyramid:scaffolds/starter/+package+/static/', + '*', + ], ] for index, line in enumerate(L[2:]): @@ -458,6 +487,7 @@ class TestPRoutesCommand(unittest.TestCase): def test_route_no_view(self): from pyramid.renderers import null_renderer as nr + config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='POST') @@ -469,27 +499,23 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual(len(L), 3) compare_to = L[-1].split() - expected = [ - 'foo', '/a/b', - '<unknown>', - 'POST', - ] + expected = ['foo', '/a/b', '<unknown>', 'POST'] self.assertEqual(compare_to, expected) def test_route_as_wsgiapp(self): from pyramid.wsgi import wsgiapp2 config1 = self._makeConfig(autocommit=True) - def view1(context, request): return 'view1' + + def view1(context, request): + return 'view1' + config1.add_route('foo', '/a/b', request_method='POST') config1.add_view(view=view1, route_name='foo') config2 = self._makeConfig(autocommit=True) config2.add_route('foo', '/a/b', request_method='POST') - config2.add_view( - wsgiapp2(config1.make_wsgi_app()), - route_name='foo', - ) + config2.add_view(wsgiapp2(config1.make_wsgi_app()), route_name='foo') command = self._makeOne() L = [] @@ -499,18 +525,15 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual(len(L), 3) compare_to = L[-1].split() - expected = [ - 'foo', '/a/b', - '<wsgiapp>', - 'POST', - ] + expected = ['foo', '/a/b', '<wsgiapp>', 'POST'] self.assertEqual(compare_to, expected) def test_route_is_get_view_request_method_not_post(self): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='GET') @@ -518,7 +541,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -530,9 +553,10 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', + 'foo', + '/a/b', 'tests.test_scripts.test_proutes.view1', - 'GET' + 'GET', ] self.assertEqual(compare_to, expected) @@ -540,7 +564,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -548,7 +573,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -560,9 +585,10 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', + 'foo', + '/a/b', 'tests.test_scripts.test_proutes.view1', - '!POST,*' + '!POST,*', ] self.assertEqual(compare_to, expected) @@ -570,8 +596,11 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' - def view2(context, request): return 'view2' + def view1(context, request): + return 'view1' + + def view2(context, request): + return 'view2' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -579,7 +608,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) config.add_route('bar', '/b/a') @@ -587,7 +616,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='bar', view=view2, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -601,9 +630,10 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(len(L), 3) compare_to = L[-1].split() expected = [ - 'foo', '/a/b', + 'foo', + '/a/b', 'tests.test_scripts.test_proutes.view1', - '!POST,*' + '!POST,*', ] self.assertEqual(compare_to, expected) @@ -611,7 +641,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -619,7 +650,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -641,7 +672,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -649,7 +681,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -670,7 +702,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -678,7 +711,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -687,7 +720,8 @@ class TestPRoutesCommand(unittest.TestCase): command.out = L.append command.bootstrap = dummy.DummyBootstrap(registry=config.registry) command.get_config_loader = dummy.DummyLoader( - {'proutes': {'format': 'method\nname'}}) + {'proutes': {'format': 'method\nname'}} + ) result = command.run() self.assertEqual(result, 0) @@ -702,7 +736,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -710,7 +745,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -719,7 +754,8 @@ class TestPRoutesCommand(unittest.TestCase): command.out = L.append command.bootstrap = dummy.DummyBootstrap(registry=config.registry) command.get_config_loader = dummy.DummyLoader( - {'proutes': {'format': 'method name'}}) + {'proutes': {'format': 'method name'}} + ) result = command.run() self.assertEqual(result, 0) @@ -734,7 +770,8 @@ class TestPRoutesCommand(unittest.TestCase): from pyramid.renderers import null_renderer as nr from pyramid.config import not_ - def view1(context, request): return 'view1' + def view1(context, request): + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -742,7 +779,7 @@ class TestPRoutesCommand(unittest.TestCase): route_name='foo', view=view1, renderer=nr, - request_method=not_('POST') + request_method=not_('POST'), ) command = self._makeOne() @@ -751,7 +788,8 @@ class TestPRoutesCommand(unittest.TestCase): command.out = L.append command.bootstrap = dummy.DummyBootstrap(registry=config.registry) command.get_config_loader = dummy.DummyLoader( - {'proutes': {'format': 'method,name'}}) + {'proutes': {'format': 'method,name'}} + ) result = command.run() self.assertEqual(result, 0) @@ -776,15 +814,14 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(result, 0) self.assertEqual(len(L), 3) compare_to = L[-1].split() - expected = [ - 'foo', 'http://example.com/bar.aspx', - '<unknown>', '*', - ] + expected = ['foo', 'http://example.com/bar.aspx', '<unknown>', '*'] self.assertEqual(compare_to, expected) + class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.proutes import main + return main(argv, quiet=True) def test_it(self): diff --git a/tests/test_scripts/test_pserve.py b/tests/test_scripts/test_pserve.py index 0c46b5348..b85f4ddb7 100644 --- a/tests/test_scripts/test_pserve.py +++ b/tests/test_scripts/test_pserve.py @@ -9,6 +9,7 @@ here = os.path.abspath(os.path.dirname(__file__)) class TestPServeCommand(unittest.TestCase): def setUp(self): from pyramid.compat import NativeIO + self.out_ = NativeIO() def out(self, msg): @@ -16,6 +17,7 @@ class TestPServeCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.pserve import PServeCommand + return PServeCommand def _makeOne(self, *args): @@ -41,6 +43,7 @@ class TestPServeCommand(unittest.TestCase): app.name = name app.global_conf = global_conf return app + self.loader.get_wsgi_app = get_app self.loader.server = lambda x: x @@ -54,41 +57,36 @@ class TestPServeCommand(unittest.TestCase): def test_config_file_finds_watch_files(self): inst = self._makeOne('development.ini') loader = self.loader('/base/path.ini') - loader.settings = {'pserve': { - 'watch_files': 'foo\n/baz\ntests.test_scripts:*.py', - }} + loader.settings = { + 'pserve': {'watch_files': 'foo\n/baz\ntests.test_scripts:*.py'} + } inst.pserve_file_config(loader, global_conf={'a': '1'}) - self.assertEqual(loader.calls[0]['defaults'], { - 'a': '1', - }) - self.assertEqual(inst.watch_files, set([ - os.path.abspath('/base/foo'), - os.path.abspath('/baz'), - os.path.abspath(os.path.join(here, '*.py')), - ])) + self.assertEqual(loader.calls[0]['defaults'], {'a': '1'}) + self.assertEqual( + inst.watch_files, + set( + [ + os.path.abspath('/base/foo'), + os.path.abspath('/baz'), + os.path.abspath(os.path.join(here, '*.py')), + ] + ), + ) def test_config_file_finds_open_url(self): inst = self._makeOne('development.ini') loader = self.loader('/base/path.ini') - loader.settings = {'pserve': { - 'open_url': 'http://127.0.0.1:8080/', - }} + loader.settings = {'pserve': {'open_url': 'http://127.0.0.1:8080/'}} inst.pserve_file_config(loader, global_conf={'a': '1'}) - self.assertEqual(loader.calls[0]['defaults'], { - 'a': '1', - }) + self.assertEqual(loader.calls[0]['defaults'], {'a': '1'}) self.assertEqual(inst.open_url, 'http://127.0.0.1:8080/') def test_guess_server_url(self): inst = self._makeOne('development.ini') loader = self.loader('/base/path.ini') - loader.settings = {'server:foo': { - 'port': '8080', - }} + loader.settings = {'server:foo': {'port': '8080'}} url = inst.guess_server_url(loader, 'foo', global_conf={'a': '1'}) - self.assertEqual(loader.calls[0]['defaults'], { - 'a': '1', - }) + self.assertEqual(loader.calls[0]['defaults'], {'a': '1'}) self.assertEqual(url, 'http://127.0.0.1:8080') def test_reload_call_hupper_with_correct_args(self): @@ -105,25 +103,35 @@ class TestPServeCommand(unittest.TestCase): orig_hupper = pserve.hupper try: - pserve.hupper = AttrDict(is_active=lambda: False, - start_reloader=dummy_start_reloader) + pserve.hupper = AttrDict( + is_active=lambda: False, start_reloader=dummy_start_reloader + ) inst = self._makeOne('--reload', 'development.ini') inst.run() finally: pserve.hupper = orig_hupper - self.assertEquals(dummy_start_reloader.args, ('pyramid.scripts.pserve.main',)) - self.assertEquals(dummy_start_reloader.kwargs, { - 'reload_interval': 1, - 'verbose': 1, - 'worker_kwargs': {'argv': ['pserve', '--reload', 'development.ini'], - 'quiet': False}}) + self.assertEquals( + dummy_start_reloader.args, ('pyramid.scripts.pserve.main',) + ) + self.assertEquals( + dummy_start_reloader.kwargs, + { + 'reload_interval': 1, + 'verbose': 1, + 'worker_kwargs': { + 'argv': ['pserve', '--reload', 'development.ini'], + 'quiet': False, + }, + }, + ) class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.pserve import main + return main(argv, quiet=True) def test_it(self): diff --git a/tests/test_scripts/test_pshell.py b/tests/test_scripts/test_pshell.py index 291714340..6beaacda6 100644 --- a/tests/test_scripts/test_pshell.py +++ b/tests/test_scripts/test_pshell.py @@ -6,10 +6,16 @@ from . import dummy class TestPShellCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.pshell import PShellCommand + return PShellCommand - def _makeOne(self, patch_bootstrap=True, patch_loader=True, - patch_args=True, patch_options=True): + def _makeOne( + self, + patch_bootstrap=True, + patch_loader=True, + patch_args=True, + patch_options=True, + ): cmd = self._getTargetClass()([]) if patch_bootstrap: @@ -19,12 +25,18 @@ class TestPShellCommand(unittest.TestCase): self.loader = dummy.DummyLoader() cmd.get_config_loader = self.loader if patch_args: - class Args(object): pass + + class Args(object): + pass + self.args = Args() self.args.config_uri = '/foo/bar/myapp.ini#myapp' cmd.args.config_uri = self.args.config_uri if patch_options: - class Options(object): pass + + class Options(object): + pass + self.options = Options() self.options.python_shell = '' self.options.setup = None @@ -47,12 +59,16 @@ class TestPShellCommand(unittest.TestCase): command.default_runner = shell command.run() self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': self.bootstrap.root, + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) @@ -84,23 +100,23 @@ class TestPShellCommand(unittest.TestCase): shell = dummy.DummyShell() bad_shell = dummy.DummyShell() self._makeEntryPoints( - command, - { - 'ipython': shell, - 'bpython': bad_shell, - } + command, {'ipython': shell, 'bpython': bad_shell} ) command.args.python_shell = 'ipython' command.run() self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': self.bootstrap.root, + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) @@ -108,13 +124,7 @@ class TestPShellCommand(unittest.TestCase): command = self._makeOne() dshell = dummy.DummyShell() - self._makeEntryPoints( - command, - { - 'ipython': dshell, - 'bpython': dshell, - } - ) + self._makeEntryPoints(command, {'ipython': dshell, 'bpython': dshell}) command.default_runner = None shell = command.make_shell() @@ -137,12 +147,7 @@ class TestPShellCommand(unittest.TestCase): self.assertRaises(ValueError, command.make_shell) self._makeEntryPoints( - command, - { - 'ipython': ipshell, - 'bpython': bpshell, - 'python': dshell, - } + command, {'ipython': ipshell, 'bpython': bpshell, 'python': dshell} ) command.args.python_shell = 'ipython' @@ -164,12 +169,7 @@ class TestPShellCommand(unittest.TestCase): dshell = dummy.DummyShell() self._makeEntryPoints( - command, - { - 'ipython': ipshell, - 'bpython': bpshell, - 'python': dshell, - } + command, {'ipython': ipshell, 'bpython': bpshell, 'python': dshell} ) command.default_runner = dshell @@ -194,41 +194,52 @@ class TestPShellCommand(unittest.TestCase): shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'm':model, - 'User': user, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': self.bootstrap.root, + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'm': model, + 'User': user, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) def test_command_setup(self): command = self._makeOne() + def setup(env): env['a'] = 1 env['root'] = 'root override' env['none'] = None + self.loader.settings = {'pshell': {'setup': setup}} shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, - 'none': None, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': 'root override', + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'a': 1, + 'none': None, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) def test_command_setup_generator(self): command = self._makeOne() did_resume_after_yield = {} + def setup(env): env['a'] = 1 env['root'] = 'root override' @@ -237,18 +248,23 @@ class TestPShellCommand(unittest.TestCase): yield did_resume_after_yield['result'] = True self.assertEqual(request.dummy_attr, 1) + self.loader.settings = {'pshell': {'setup': setup}} shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, - 'none': None, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': 'root override', + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'a': 1, + 'none': None, + }, + ) self.assertTrue(did_resume_after_yield['result']) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) @@ -257,15 +273,10 @@ class TestPShellCommand(unittest.TestCase): command = self._makeOne() ipshell = dummy.DummyShell() dshell = dummy.DummyShell() - self._makeEntryPoints( - command, - { - 'ipython': ipshell, - 'python': dshell, - } - ) - self.loader.settings = {'pshell': { - 'default_shell': 'bpython python\nipython'}} + self._makeEntryPoints(command, {'ipython': ipshell, 'python': dshell}) + self.loader.settings = { + 'pshell': {'default_shell': 'bpython python\nipython'} + } command.run() self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') self.assertTrue(dshell.called) @@ -273,78 +284,105 @@ class TestPShellCommand(unittest.TestCase): def test_command_loads_check_variable_override_order(self): command = self._makeOne() model = dummy.Dummy() + def setup(env): env['a'] = 1 env['m'] = 'model override' env['root'] = 'root override' + self.loader.settings = {'pshell': {'setup': setup, 'm': model}} shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, 'm':'model override', - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': 'root override', + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'a': 1, + 'm': 'model override', + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) def test_command_loads_setup_from_options(self): command = self._makeOne() + def setup(env): env['a'] = 1 env['root'] = 'root override' + model = dummy.Dummy() self.loader.settings = {'pshell': {'setup': 'abc', 'm': model}} command.args.setup = setup shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':'root override', - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'a':1, 'm':model, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': 'root override', + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'a': 1, + 'm': model, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) def test_command_custom_section_override(self): command = self._makeOne() dummy_ = dummy.Dummy() - self.loader.settings = {'pshell': { - 'app': dummy_, 'root': dummy_, 'registry': dummy_, - 'request': dummy_}} + self.loader.settings = { + 'pshell': { + 'app': dummy_, + 'root': dummy_, + 'registry': dummy_, + 'request': dummy_, + } + } shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':dummy_, 'root':dummy_, 'registry':dummy_, 'request':dummy_, - 'root_factory':self.bootstrap.root_factory, - }) + self.assertEqual( + shell.env, + { + 'app': dummy_, + 'root': dummy_, + 'registry': dummy_, + 'request': dummy_, + 'root_factory': self.bootstrap.root_factory, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) def test_command_loads_pythonstartup(self): command = self._makeOne() - command.pystartup = ( - os.path.abspath( - os.path.join( - os.path.dirname(__file__), - 'pystartup.txt'))) + command.pystartup = os.path.abspath( + os.path.join(os.path.dirname(__file__), 'pystartup.txt') + ) shell = dummy.DummyShell() command.run(shell) self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.env, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - 'foo':1, - }) + self.assertEqual( + shell.env, + { + 'app': self.bootstrap.app, + 'root': self.bootstrap.root, + 'registry': self.bootstrap.registry, + 'request': self.bootstrap.request, + 'root_factory': self.bootstrap.root_factory, + 'foo': 1, + }, + ) self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) @@ -359,27 +397,20 @@ class TestPShellCommand(unittest.TestCase): command.out = out - self._makeEntryPoints( - command, - { - 'ipython': dshell, - 'python': dshell, - } - ) + self._makeEntryPoints(command, {'ipython': dshell, 'python': dshell}) command.args.list = True result = command.run() self.assertEqual(result, 0) - self.assertEqual(out_calls, [ - 'Available shells:', - ' ipython', - ' python', - ]) + self.assertEqual( + out_calls, ['Available shells:', ' ipython', ' python'] + ) class Test_python_shell_runner(unittest.TestCase): def _callFUT(self, env, help, interact): from pyramid.scripts.pshell import python_shell_runner + return python_shell_runner(env, help, interact=interact) def test_it(self): @@ -388,9 +419,11 @@ class Test_python_shell_runner(unittest.TestCase): self.assertEqual(interact.local, {'foo': 'bar'}) self.assertTrue('a help message' in interact.banner) + class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.pshell import main + return main(argv, quiet=True) def test_it(self): diff --git a/tests/test_scripts/test_ptweens.py b/tests/test_scripts/test_ptweens.py index 4ad015249..a7fe6f651 100644 --- a/tests/test_scripts/test_ptweens.py +++ b/tests/test_scripts/test_ptweens.py @@ -1,9 +1,11 @@ import unittest from . import dummy + class TestPTweensCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.ptweens import PTweensCommand + return PTweensCommand def _makeOne(self): @@ -31,9 +33,10 @@ class TestPTweensCommand(unittest.TestCase): result = command.run() self.assertEqual(result, 0) self.assertEqual( - L[0], - '"pyramid.tweens" config value NOT set (implicitly ordered tweens ' - 'used)') + L[0], + '"pyramid.tweens" config value NOT set (implicitly ordered tweens ' + 'used)', + ) def test_command_implicit_and_explicit_tweens(self): command = self._makeOne() @@ -44,17 +47,20 @@ class TestPTweensCommand(unittest.TestCase): result = command.run() self.assertEqual(result, 0) self.assertEqual( - L[0], - '"pyramid.tweens" config value set (explicitly ordered tweens used)') + L[0], + '"pyramid.tweens" config value set (explicitly ordered tweens used)', + ) def test__get_tweens(self): command = self._makeOne() registry = dummy.DummyRegistry() self.assertEqual(command._get_tweens(registry), None) + class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.ptweens import main + return main(argv, quiet=True) def test_it(self): diff --git a/tests/test_scripts/test_pviews.py b/tests/test_scripts/test_pviews.py index 999028f28..cdb3c1c33 100644 --- a/tests/test_scripts/test_pviews.py +++ b/tests/test_scripts/test_pviews.py @@ -1,9 +1,11 @@ import unittest from . import dummy + class TestPViewsCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.scripts.pviews import PViewsCommand + return PViewsCommand def _makeOne(self, registry=None): @@ -15,17 +17,20 @@ class TestPViewsCommand(unittest.TestCase): def _makeRequest(self, url, registry): from pyramid.request import Request + request = Request.blank('/a') request.registry = registry return request def _register_mapper(self, registry, routes): from pyramid.interfaces import IRoutesMapper + mapper = dummy.DummyMapper(*routes) registry.registerUtility(mapper, IRoutesMapper) def test__find_view_no_match(self): from pyramid.registry import Registry + registry = Registry() self._register_mapper(registry, []) command = self._makeOne(registry) @@ -41,16 +46,19 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.traversal import DefaultRootFactory from pyramid.registry import Registry + registry = Registry() + @implementer(IMultiView) class View1(object): pass - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + + request = dummy.DummyRequest({'PATH_INFO': '/a'}) root = DefaultRootFactory(request) root_iface = providedBy(root) - registry.registerAdapter(View1(), - (IViewClassifier, IRequest, root_iface), - IMultiView) + registry.registerAdapter( + View1(), (IViewClassifier, IRequest, root_iface), IMultiView + ) self._register_mapper(registry, []) command = self._makeOne(registry=registry) request = self._makeRequest('/x', registry) @@ -64,14 +72,18 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IView from pyramid.traversal import DefaultRootFactory from pyramid.registry import Registry + registry = Registry() - def view1(): pass - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + + def view1(): + pass + + request = dummy.DummyRequest({'PATH_INFO': '/a'}) root = DefaultRootFactory(request) root_iface = providedBy(root) - registry.registerAdapter(view1, - (IViewClassifier, IRequest, root_iface), - IView, name='a') + registry.registerAdapter( + view1, (IViewClassifier, IRequest, root_iface), IView, name='a' + ) self._register_mapper(registry, []) command = self._makeOne(registry=registry) request = self._makeRequest('/a', registry) @@ -86,17 +98,20 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.traversal import DefaultRootFactory from pyramid.registry import Registry + registry = Registry() + @implementer(IMultiView) class View1(object): pass - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + + request = dummy.DummyRequest({'PATH_INFO': '/a'}) root = DefaultRootFactory(request) root_iface = providedBy(root) view = View1() - registry.registerAdapter(view, - (IViewClassifier, IRequest, root_iface), - IMultiView, name='a') + registry.registerAdapter( + view, (IViewClassifier, IRequest, root_iface), IMultiView, name='a' + ) self._register_mapper(registry, []) command = self._makeOne(registry=registry) request = self._makeRequest('/a', registry) @@ -110,22 +125,32 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView from pyramid.registry import Registry + registry = Registry() - def view():pass + + def view(): + pass + class IMyRoot(Interface): pass + class IMyRoute(Interface): pass - registry.registerAdapter(view, - (IViewClassifier, IMyRoute, IMyRoot), - IView, '') + + registry.registerAdapter( + view, (IViewClassifier, IMyRoute, IMyRoot), IView, '' + ) registry.registerUtility(IMyRoute, IRouteRequest, name='a') + @implementer(IMyRoot) class Factory(object): def __init__(self, request): pass - routes = [dummy.DummyRoute('a', '/a', factory=Factory, matchdict={}), - dummy.DummyRoute('b', '/b', factory=Factory)] + + routes = [ + dummy.DummyRoute('a', '/a', factory=Factory, matchdict={}), + dummy.DummyRoute('b', '/b', factory=Factory), + ] self._register_mapper(registry, routes) command = self._makeOne(registry=registry) request = self._makeRequest('/a', registry) @@ -139,24 +164,37 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IRootFactory from pyramid.registry import Registry + registry = Registry() - def view1():pass - def view2():pass + + def view1(): + pass + + def view2(): + pass + class IMyRoot(Interface): pass + class IMyRoute1(Interface): pass + class IMyRoute2(Interface): pass + registry.registerUtility(IMyRoute1, IRouteRequest, name='a') registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) class Factory(object): def __init__(self, request): pass + registry.registerUtility(Factory, IRootFactory) - routes = [dummy.DummyRoute('a', '/a', matchdict={}), - dummy.DummyRoute('b', '/a', matchdict={})] + routes = [ + dummy.DummyRoute('a', '/a', matchdict={}), + dummy.DummyRoute('b', '/a', matchdict={}), + ] self._register_mapper(registry, routes) command = self._makeOne(registry=registry) request = self._makeRequest('/a', registry) @@ -172,30 +210,43 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.interfaces import IMultiView from pyramid.interfaces import IRootFactory from pyramid.registry import Registry + registry = Registry() - def view1():pass - def view2():pass + + def view1(): + pass + + def view2(): + pass + class IMyRoot(Interface): pass + class IMyRoute1(Interface): pass + class IMyRoute2(Interface): pass - registry.registerAdapter(view1, - (IViewClassifier, IMyRoute1, IMyRoot), - IView, '') - registry.registerAdapter(view2, - (IViewClassifier, IMyRoute2, IMyRoot), - IView, '') + + registry.registerAdapter( + view1, (IViewClassifier, IMyRoute1, IMyRoot), IView, '' + ) + registry.registerAdapter( + view2, (IViewClassifier, IMyRoute2, IMyRoot), IView, '' + ) registry.registerUtility(IMyRoute1, IRouteRequest, name='a') registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) class Factory(object): def __init__(self, request): pass + registry.registerUtility(Factory, IRootFactory) - routes = [dummy.DummyRoute('a', '/a', matchdict={}), - dummy.DummyRoute('b', '/a', matchdict={})] + routes = [ + dummy.DummyRoute('a', '/a', matchdict={}), + dummy.DummyRoute('b', '/a', matchdict={}), + ] self._register_mapper(registry, routes) command = self._makeOne(registry=registry) request = self._makeRequest('/a', registry) @@ -207,37 +258,58 @@ class TestPViewsCommand(unittest.TestCase): def test__find_multi_routes_all_match(self): command = self._makeOne() - def factory(request): pass - routes = [dummy.DummyRoute('a', '/a', factory=factory, matchdict={}), - dummy.DummyRoute('b', '/a', factory=factory, matchdict={})] + + def factory(request): + pass + + routes = [ + dummy.DummyRoute('a', '/a', factory=factory, matchdict={}), + dummy.DummyRoute('b', '/a', factory=factory, matchdict={}), + ] mapper = dummy.DummyMapper(*routes) - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + request = dummy.DummyRequest({'PATH_INFO': '/a'}) result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':{}, 'route':routes[0]}, - {'match':{}, 'route':routes[1]}]) - + self.assertEqual( + result, + [ + {'match': {}, 'route': routes[0]}, + {'match': {}, 'route': routes[1]}, + ], + ) + def test__find_multi_routes_some_match(self): command = self._makeOne() - def factory(request): pass - routes = [dummy.DummyRoute('a', '/a', factory=factory), - dummy.DummyRoute('b', '/a', factory=factory, matchdict={})] + + def factory(request): + pass + + routes = [ + dummy.DummyRoute('a', '/a', factory=factory), + dummy.DummyRoute('b', '/a', factory=factory, matchdict={}), + ] mapper = dummy.DummyMapper(*routes) - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + request = dummy.DummyRequest({'PATH_INFO': '/a'}) result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':{}, 'route':routes[1]}]) - + self.assertEqual(result, [{'match': {}, 'route': routes[1]}]) + def test__find_multi_routes_none_match(self): command = self._makeOne() - def factory(request): pass - routes = [dummy.DummyRoute('a', '/a', factory=factory), - dummy.DummyRoute('b', '/a', factory=factory)] + + def factory(request): + pass + + routes = [ + dummy.DummyRoute('a', '/a', factory=factory), + dummy.DummyRoute('b', '/a', factory=factory), + ] mapper = dummy.DummyMapper(*routes) - request = dummy.DummyRequest({'PATH_INFO':'/a'}) + request = dummy.DummyRequest({'PATH_INFO': '/a'}) result = command._find_multi_routes(mapper, request) self.assertEqual(result, []) - + def test_views_command_not_found(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -252,6 +324,7 @@ class TestPViewsCommand(unittest.TestCase): def test_views_command_not_found_url_starts_without_slash(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -266,6 +339,7 @@ class TestPViewsCommand(unittest.TestCase): def test_views_command_single_view_traversal(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -279,16 +353,19 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.DummyView') + self.assertEqual(L[8], ' tests.test_scripts.dummy.DummyView') def test_views_command_single_view_function_traversal(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] command.out = L.append - def view(): pass + + def view(): + pass + view.__request_attrs__ = {'context': 'context', 'view_name': 'a'} command._find_view = lambda arg1: view command.args.config_uri = '/foo/bar/myapp.ini#myapp' @@ -298,11 +375,11 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.test_pviews.view') + self.assertEqual(L[8], ' tests.test_scripts.test_pviews.view') def test_views_command_single_view_traversal_with_permission(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -317,17 +394,20 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.DummyView') + self.assertEqual(L[8], ' tests.test_scripts.dummy.DummyView') self.assertEqual(L[9], ' required permission = test') def test_views_command_single_view_traversal_with_predicates(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] command.out = L.append - def predicate(): pass + + def predicate(): + pass + predicate.text = lambda *arg: "predicate = x" view = dummy.DummyView(context='context', view_name='a') view.__predicates__ = [predicate] @@ -339,19 +419,20 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.DummyView') + self.assertEqual(L[8], ' tests.test_scripts.dummy.DummyView') self.assertEqual(L[9], ' view predicates (predicate = x)') def test_views_command_single_view_route(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] command.out = L.append route = dummy.DummyRoute('a', '/a', matchdict={}) - view = dummy.DummyView(context='context', view_name='a', - matched_route=route, subpath='') + view = dummy.DummyView( + context='context', view_name='a', matched_route=route, subpath='' + ) command._find_view = lambda arg1: view command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -365,11 +446,11 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[9], ' route pattern: /a') self.assertEqual(L[10], ' route path: /a') self.assertEqual(L[11], ' subpath: ') - self.assertEqual(L[15], - ' tests.test_scripts.dummy.DummyView') + self.assertEqual(L[15], ' tests.test_scripts.dummy.DummyView') def test_views_command_multi_view_nested(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -377,10 +458,12 @@ class TestPViewsCommand(unittest.TestCase): view1 = dummy.DummyView(context='context', view_name='a1') view1.__name__ = 'view1' view1.__view_attr__ = 'call' - multiview1 = dummy.DummyMultiView(view1, context='context', - view_name='a1') - multiview2 = dummy.DummyMultiView(multiview1, context='context', - view_name='a') + multiview1 = dummy.DummyMultiView( + view1, context='context', view_name='a1' + ) + multiview2 = dummy.DummyMultiView( + multiview1, context='context', view_name='a' + ) command._find_view = lambda arg1: multiview2 command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -389,22 +472,25 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.DummyMultiView') - self.assertEqual(L[12], - ' tests.test_scripts.dummy.view1.call') + self.assertEqual(L[8], ' tests.test_scripts.dummy.DummyMultiView') + self.assertEqual(L[12], ' tests.test_scripts.dummy.view1.call') def test_views_command_single_view_route_with_route_predicates(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] command.out = L.append - def predicate(): pass + + def predicate(): + pass + predicate.text = lambda *arg: "predicate = x" route = dummy.DummyRoute('a', '/a', matchdict={}, predicate=predicate) - view = dummy.DummyView(context='context', view_name='a', - matched_route=route, subpath='') + view = dummy.DummyView( + context='context', view_name='a', matched_route=route, subpath='' + ) command._find_view = lambda arg1: view command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -419,11 +505,11 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[10], ' route path: /a') self.assertEqual(L[11], ' subpath: ') self.assertEqual(L[12], ' route predicates (predicate = x)') - self.assertEqual(L[16], - ' tests.test_scripts.dummy.DummyView') + self.assertEqual(L[16], ' tests.test_scripts.dummy.DummyView') def test_views_command_multiview(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -431,7 +517,9 @@ class TestPViewsCommand(unittest.TestCase): view = dummy.DummyView(context='context') view.__name__ = 'view' view.__view_attr__ = 'call' - multiview = dummy.DummyMultiView(view, context='context', view_name='a') + multiview = dummy.DummyMultiView( + view, context='context', view_name='a' + ) command._find_view = lambda arg1: multiview command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -440,11 +528,11 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.view.call') + self.assertEqual(L[8], ' tests.test_scripts.dummy.view.call') def test_views_command_multiview_with_permission(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] @@ -453,7 +541,9 @@ class TestPViewsCommand(unittest.TestCase): view.__name__ = 'view' view.__view_attr__ = 'call' view.__permission__ = 'test' - multiview = dummy.DummyMultiView(view, context='context', view_name='a') + multiview = dummy.DummyMultiView( + view, context='context', view_name='a' + ) command._find_view = lambda arg1: multiview command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -462,23 +552,28 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.view.call') + self.assertEqual(L[8], ' tests.test_scripts.dummy.view.call') self.assertEqual(L[9], ' required permission = test') def test_views_command_multiview_with_predicates(self): from pyramid.registry import Registry + registry = Registry() command = self._makeOne(registry=registry) L = [] command.out = L.append - def predicate(): pass + + def predicate(): + pass + predicate.text = lambda *arg: "predicate = x" view = dummy.DummyView(context='context') view.__name__ = 'view' view.__view_attr__ = 'call' view.__predicates__ = [predicate] - multiview = dummy.DummyMultiView(view, context='context', view_name='a') + multiview = dummy.DummyMultiView( + view, context='context', view_name='a' + ) command._find_view = lambda arg1: multiview command.args.config_uri = '/foo/bar/myapp.ini#myapp' command.args.url = '/a' @@ -487,13 +582,14 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[1], 'URL = /a') self.assertEqual(L[3], ' context: context') self.assertEqual(L[4], ' view name: a') - self.assertEqual(L[8], - ' tests.test_scripts.dummy.view.call') + self.assertEqual(L[8], ' tests.test_scripts.dummy.view.call') self.assertEqual(L[9], ' view predicates (predicate = x)') + class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.pviews import main + return main(argv, quiet=True) def test_it(self): diff --git a/tests/test_security.py b/tests/test_security.py index e5399ecdf..a11035d85 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -2,6 +2,7 @@ import unittest from pyramid import testing + class TestAllPermissionsList(unittest.TestCase): def setUp(self): testing.setUp() @@ -11,6 +12,7 @@ class TestAllPermissionsList(unittest.TestCase): def _getTargetClass(self): from pyramid.security import AllPermissionsList + return AllPermissionsList def _makeOne(self): @@ -44,13 +46,16 @@ class TestAllPermissionsList(unittest.TestCase): def test_singleton(self): from pyramid.security import ALL_PERMISSIONS + self.assertEqual(ALL_PERMISSIONS.__class__, self._getTargetClass()) + class TestAllowed(unittest.TestCase): def _getTargetClass(self): from pyramid.security import Allowed + return Allowed - + def _makeOne(self, *arg, **kw): klass = self._getTargetClass() return klass(*arg, **kw) @@ -64,11 +69,13 @@ class TestAllowed(unittest.TestCase): self.assertTrue('<Allowed instance at ' in repr(allowed)) self.assertTrue("with msg 'hello'>" in repr(allowed)) + class TestDenied(unittest.TestCase): def _getTargetClass(self): from pyramid.security import Denied + return Denied - + def _makeOne(self, *arg, **kw): klass = self._getTargetClass() return klass(*arg, **kw) @@ -82,20 +89,27 @@ class TestDenied(unittest.TestCase): self.assertTrue('<Denied instance at ' in repr(denied)) self.assertTrue("with msg 'hello'>" in repr(denied)) + class TestACLAllowed(unittest.TestCase): def _getTargetClass(self): from pyramid.security import ACLAllowed + return ACLAllowed - + def _makeOne(self, *arg, **kw): klass = self._getTargetClass() return klass(*arg, **kw) def test_it(self): from pyramid.security import Allowed - msg = ("ACLAllowed permission 'permission' via ACE 'ace' in ACL 'acl' " - "on context 'ctx' for principals 'principals'") - allowed = self._makeOne('ace', 'acl', 'permission', 'principals', 'ctx') + + msg = ( + "ACLAllowed permission 'permission' via ACE 'ace' in ACL 'acl' " + "on context 'ctx' for principals 'principals'" + ) + allowed = self._makeOne( + 'ace', 'acl', 'permission', 'principals', 'ctx' + ) self.assertIsInstance(allowed, Allowed) self.assertTrue(msg in allowed.msg) self.assertEqual(allowed, True) @@ -104,19 +118,24 @@ class TestACLAllowed(unittest.TestCase): self.assertTrue('<ACLAllowed instance at ' in repr(allowed)) self.assertTrue("with msg %r>" % msg in repr(allowed)) + class TestACLDenied(unittest.TestCase): def _getTargetClass(self): from pyramid.security import ACLDenied + return ACLDenied - + def _makeOne(self, *arg, **kw): klass = self._getTargetClass() return klass(*arg, **kw) def test_it(self): from pyramid.security import Denied - msg = ("ACLDenied permission 'permission' via ACE 'ace' in ACL 'acl' " - "on context 'ctx' for principals 'principals'") + + msg = ( + "ACLDenied permission 'permission' via ACE 'ace' in ACL 'acl' " + "on context 'ctx' for principals 'principals'" + ) denied = self._makeOne('ace', 'acl', 'permission', 'principals', 'ctx') self.assertIsInstance(denied, Denied) self.assertTrue(msg in denied.msg) @@ -126,6 +145,7 @@ class TestACLDenied(unittest.TestCase): self.assertTrue('<ACLDenied instance at ' in repr(denied)) self.assertTrue("with msg %r>" % msg in repr(denied)) + class TestPrincipalsAllowedByPermission(unittest.TestCase): def setUp(self): testing.setUp() @@ -135,31 +155,36 @@ class TestPrincipalsAllowedByPermission(unittest.TestCase): def _callFUT(self, *arg): from pyramid.security import principals_allowed_by_permission + return principals_allowed_by_permission(*arg) def test_no_authorization_policy(self): from pyramid.security import Everyone + context = DummyContext() result = self._callFUT(context, 'view') self.assertEqual(result, [Everyone]) def test_with_authorization_policy(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() _registerAuthorizationPolicy(registry, 'yo') context = DummyContext() result = self._callFUT(context, 'view') self.assertEqual(result, 'yo') + class TestRemember(unittest.TestCase): def setUp(self): testing.setUp() - + def tearDown(self): testing.tearDown() def _callFUT(self, *arg, **kwarg): from pyramid.security import remember + return remember(*arg, **kwarg) def test_no_authentication_policy(self): @@ -176,6 +201,7 @@ class TestRemember(unittest.TestCase): def test_with_authentication_policy_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = _makeRequest() del request.registry @@ -189,15 +215,17 @@ class TestRemember(unittest.TestCase): _registerAuthenticationPolicy(registry, 'yo') self.assertRaises(TypeError, lambda: self._callFUT(request)) + class TestForget(unittest.TestCase): def setUp(self): testing.setUp() - + def tearDown(self): testing.tearDown() def _callFUT(self, *arg): from pyramid.security import forget + return forget(*arg) def test_no_authentication_policy(self): @@ -213,22 +241,25 @@ class TestForget(unittest.TestCase): def test_with_authentication_policy_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = _makeRequest() del request.registry _registerAuthenticationPolicy(registry, 'yo') result = self._callFUT(request) self.assertEqual(result, [('X-Pyramid-Test', 'logout')]) - + + class TestViewExecutionPermitted(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() - + def _callFUT(self, *arg, **kw): from pyramid.security import view_execution_permitted + return view_execution_permitted(*arg, **kw) def _registerSecuredView(self, view_name, allow=True): @@ -236,15 +267,21 @@ class TestViewExecutionPermitted(unittest.TestCase): from zope.interface import Interface from pyramid.interfaces import ISecuredView from pyramid.interfaces import IViewClassifier + class Checker(object): def __permitted__(self, context, request): self.context = context self.request = request return allow + checker = Checker() reg = get_current_registry() - reg.registerAdapter(checker, (IViewClassifier, Interface, Interface), - ISecuredView, view_name) + reg.registerAdapter( + checker, + (IViewClassifier, Interface, Interface), + ISecuredView, + view_name, + ) return checker def test_no_permission(self): @@ -253,16 +290,20 @@ class TestViewExecutionPermitted(unittest.TestCase): from pyramid.interfaces import ISettings from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier + settings = dict(debug_authorization=True) reg = get_current_registry() reg.registerUtility(settings, ISettings) context = DummyContext() request = testing.DummyRequest({}) + class DummyView(object): pass + view = DummyView() - reg.registerAdapter(view, (IViewClassifier, Interface, Interface), - IView, '') + reg.registerAdapter( + view, (IViewClassifier, Interface, Interface), IView, '' + ) result = self._callFUT(context, request, '') msg = result.msg self.assertTrue("Allowed: view name '' in context" in msg) @@ -272,6 +313,7 @@ class TestViewExecutionPermitted(unittest.TestCase): def test_no_view_registered(self): from pyramid.threadlocal import get_current_registry from pyramid.interfaces import ISettings + settings = dict(debug_authorization=True) reg = get_current_registry() reg.registerUtility(settings, ISettings) @@ -283,8 +325,10 @@ class TestViewExecutionPermitted(unittest.TestCase): from zope.interface import Interface from zope.interface import directlyProvides from pyramid.interfaces import IRequest + class IContext(Interface): pass + context = DummyContext() directlyProvides(context, IContext) self._registerSecuredView('', True) @@ -293,23 +337,25 @@ class TestViewExecutionPermitted(unittest.TestCase): result = self._callFUT(context, request, '') self.assertTrue(result) + class TestAuthenticatedUserId(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() - + def test_backward_compat_delegates_to_mixin(self): from zope.deprecation import __show__ + try: __show__.off() request = _makeFakeRequest() from pyramid.security import authenticated_userid + self.assertEqual( - authenticated_userid(request), - 'authenticated_userid' - ) + authenticated_userid(request), 'authenticated_userid' + ) finally: __show__.on() @@ -324,29 +370,32 @@ class TestAuthenticatedUserId(unittest.TestCase): def test_with_authentication_policy_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = _makeRequest() del request.registry _registerAuthenticationPolicy(registry, 'yo') self.assertEqual(request.authenticated_userid, 'yo') + class TestUnAuthenticatedUserId(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() - + def test_backward_compat_delegates_to_mixin(self): from zope.deprecation import __show__ + try: __show__.off() request = _makeFakeRequest() from pyramid.security import unauthenticated_userid + self.assertEqual( - unauthenticated_userid(request), - 'unauthenticated_userid', - ) + unauthenticated_userid(request), 'unauthenticated_userid' + ) finally: __show__.on() @@ -361,34 +410,38 @@ class TestUnAuthenticatedUserId(unittest.TestCase): def test_with_authentication_policy_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = _makeRequest() del request.registry _registerAuthenticationPolicy(registry, 'yo') self.assertEqual(request.unauthenticated_userid, 'yo') + class TestEffectivePrincipals(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() - + def test_backward_compat_delegates_to_mixin(self): request = _makeFakeRequest() from zope.deprecation import __show__ + try: __show__.off() from pyramid.security import effective_principals + self.assertEqual( - effective_principals(request), - 'effective_principals' - ) + effective_principals(request), 'effective_principals' + ) finally: __show__.on() def test_no_authentication_policy(self): from pyramid.security import Everyone + request = _makeRequest() self.assertEqual(request.effective_principals, [Everyone]) @@ -399,22 +452,25 @@ class TestEffectivePrincipals(unittest.TestCase): def test_with_authentication_policy_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = _makeRequest() del request.registry _registerAuthenticationPolicy(registry, 'yo') self.assertEqual(request.effective_principals, 'yo') + class TestHasPermission(unittest.TestCase): def setUp(self): testing.setUp() - + def tearDown(self): testing.tearDown() def _makeOne(self): from pyramid.security import AuthorizationAPIMixin from pyramid.registry import Registry + mixin = AuthorizationAPIMixin() mixin.registry = Registry() mixin.context = object() @@ -422,10 +478,12 @@ class TestHasPermission(unittest.TestCase): def test_delegates_to_mixin(self): from zope.deprecation import __show__ + try: __show__.off() mixin = self._makeOne() from pyramid.security import has_permission + self.called_has_permission = False def mocked_has_permission(*args, **kw): @@ -446,8 +504,9 @@ class TestHasPermission(unittest.TestCase): def test_with_no_authorization_policy(self): request = self._makeOne() _registerAuthenticationPolicy(request.registry, None) - self.assertRaises(ValueError, - request.has_permission, 'view', context=None) + self.assertRaises( + ValueError, request.has_permission, 'view', context=None + ) def test_with_authn_and_authz_policies_registered(self): request = self._makeOne() @@ -457,6 +516,7 @@ class TestHasPermission(unittest.TestCase): def test_with_no_reg_on_request(self): from pyramid.threadlocal import get_current_registry + registry = get_current_registry() request = self._makeOne() del request.registry @@ -473,12 +533,15 @@ class TestHasPermission(unittest.TestCase): del request.context self.assertRaises(AttributeError, request.has_permission, 'view') + _TEST_HEADER = 'X-Pyramid-Test' + class DummyContext: def __init__(self, *arg, **kw): self.__dict__.update(kw) + class DummyAuthenticationPolicy: def __init__(self, result): self.result = result @@ -502,6 +565,7 @@ class DummyAuthenticationPolicy: self._header_forgotten = headers[0] return headers + class DummyAuthorizationPolicy: def __init__(self, result): self.result = result @@ -512,25 +576,32 @@ class DummyAuthorizationPolicy: def principals_allowed_by_permission(self, context, permission): return self.result + def _registerAuthenticationPolicy(reg, result): from pyramid.interfaces import IAuthenticationPolicy + policy = DummyAuthenticationPolicy(result) reg.registerUtility(policy, IAuthenticationPolicy) return policy + def _registerAuthorizationPolicy(reg, result): from pyramid.interfaces import IAuthorizationPolicy + policy = DummyAuthorizationPolicy(result) reg.registerUtility(policy, IAuthorizationPolicy) return policy + def _makeRequest(): from pyramid.registry import Registry + request = testing.DummyRequest(environ={}) request.registry = Registry() request.context = object() return request + def _makeFakeRequest(): class FakeRequest(testing.DummyRequest): @property @@ -546,4 +617,3 @@ def _makeFakeRequest(): return 'effective_principals' return FakeRequest({}) - diff --git a/tests/test_session.py b/tests/test_session.py index 6cd058bfb..05c257e73 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -4,8 +4,8 @@ import unittest from pyramid import testing from pyramid.compat import pickle -class SharedCookieSessionTests(object): +class SharedCookieSessionTests(object): def test_ctor_no_cookie(self): request = testing.DummyRequest() session = self._makeOne(request) @@ -14,17 +14,19 @@ class SharedCookieSessionTests(object): def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import ISession + request = testing.DummyRequest() session = self._makeOne(request) verifyObject(ISession, session) def test_ctor_with_cookie_still_valid(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1})) request.cookies['session'] = cookieval session = self._makeOne(request) - self.assertEqual(dict(session), {'state':1}) + self.assertEqual(dict(session), {'state': 1}) def test_ctor_with_cookie_expired(self): request = testing.DummyRequest() @@ -48,6 +50,7 @@ class SharedCookieSessionTests(object): def test_timeout(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time() - 5, 0, {'state': 1})) request.cookies['session'] = cookieval @@ -56,6 +59,7 @@ class SharedCookieSessionTests(object): def test_timeout_never(self): import time + request = testing.DummyRequest() LONG_TIME = 31536000 cookieval = self._serialize((time.time() + LONG_TIME, 0, {'state': 1})) @@ -65,6 +69,7 @@ class SharedCookieSessionTests(object): def test_timeout_str(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time() - 5, 0, {'state': 1})) request.cookies['session'] = cookieval @@ -73,7 +78,9 @@ class SharedCookieSessionTests(object): def test_timeout_invalid(self): request = testing.DummyRequest() - self.assertRaises(ValueError, self._makeOne, request, timeout='Invalid value') + self.assertRaises( + ValueError, self._makeOne, request, timeout='Invalid value' + ) def test_changed(self): request = testing.DummyRequest() @@ -90,6 +97,7 @@ class SharedCookieSessionTests(object): def test_reissue_triggered(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time() - 2, 0, {'state': 1})) request.cookies['session'] = cookieval @@ -107,6 +115,7 @@ class SharedCookieSessionTests(object): def test__set_cookie_on_exception_no_request_exception(self): import webob + request = testing.DummyRequest() request.exception = None session = self._makeOne(request) @@ -118,12 +127,13 @@ class SharedCookieSessionTests(object): def test__set_cookie_cookieval_too_long(self): request = testing.DummyRequest() session = self._makeOne(request) - session['abc'] = 'x'*100000 + session['abc'] = 'x' * 100000 response = DummyResponse() self.assertRaises(ValueError, session._set_cookie, response) def test__set_cookie_real_webob_response(self): import webob + request = testing.DummyRequest() session = self._makeOne(request) session['abc'] = 'x' @@ -133,21 +143,24 @@ class SharedCookieSessionTests(object): def test__set_cookie_options(self): from pyramid.response import Response + request = testing.DummyRequest() request.exception = None - session = self._makeOne(request, - cookie_name='abc', - path='/foo', - domain='localhost', - secure=True, - httponly=True, - ) + session = self._makeOne( + request, + cookie_name='abc', + path='/foo', + domain='localhost', + secure=True, + httponly=True, + ) session['abc'] = 'x' response = Response() self.assertEqual(session._set_cookie(response), True) cookieval = response.headerlist[-1][1] - val, domain, path, secure, httponly, samesite = [x.strip() for x in - cookieval.split(';')] + val, domain, path, secure, httponly, samesite = [ + x.strip() for x in cookieval.split(';') + ] self.assertTrue(val.startswith('abc=')) self.assertEqual(domain, 'Domain=localhost') self.assertEqual(path, 'Path=/foo') @@ -249,6 +262,7 @@ class SharedCookieSessionTests(object): def test_no_set_cookie_with_exception(self): import webob + request = testing.DummyRequest() request.exception = True session = self._makeOne(request, set_on_exception=False) @@ -262,6 +276,7 @@ class SharedCookieSessionTests(object): def test_set_cookie_with_exception(self): import webob + request = testing.DummyRequest() request.exception = True session = self._makeOne(request) @@ -275,6 +290,7 @@ class SharedCookieSessionTests(object): def test_cookie_is_set(self): import webob + request = testing.DummyRequest() session = self._makeOne(request) session['a'] = 1 @@ -285,9 +301,11 @@ class SharedCookieSessionTests(object): self.assertEqual(result, None) self.assertTrue('Set-Cookie' in dict(response.headerlist)) + class TestBaseCookieSession(SharedCookieSessionTests, unittest.TestCase): def _makeOne(self, request, **kw): from pyramid.session import BaseCookieSessionFactory + serializer = DummySerializer() return BaseCookieSessionFactory(serializer, **kw)(request) @@ -296,6 +314,7 @@ class TestBaseCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_not_triggered(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1})) request.cookies['session'] = cookieval @@ -313,6 +332,7 @@ class TestBaseCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_str_triggered(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time() - 2, 0, {'state': 1})) request.cookies['session'] = cookieval @@ -322,15 +342,21 @@ class TestBaseCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_invalid(self): request = testing.DummyRequest() - self.assertRaises(ValueError, self._makeOne, request, reissue_time='invalid value') + self.assertRaises( + ValueError, self._makeOne, request, reissue_time='invalid value' + ) def test_cookie_max_age_invalid(self): request = testing.DummyRequest() - self.assertRaises(ValueError, self._makeOne, request, max_age='invalid value') + self.assertRaises( + ValueError, self._makeOne, request, max_age='invalid value' + ) + class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def _makeOne(self, request, **kw): from pyramid.session import SignedCookieSessionFactory + kw.setdefault('secret', 'secret') return SignedCookieSessionFactory(**kw)(request) @@ -347,6 +373,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_not_triggered(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1})) request.cookies['session'] = cookieval @@ -364,6 +391,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_str_triggered(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time() - 2, 0, {'state': 1})) request.cookies['session'] = cookieval @@ -373,14 +401,19 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_reissue_invalid(self): request = testing.DummyRequest() - self.assertRaises(ValueError, self._makeOne, request, reissue_time='invalid value') + self.assertRaises( + ValueError, self._makeOne, request, reissue_time='invalid value' + ) def test_cookie_max_age_invalid(self): request = testing.DummyRequest() - self.assertRaises(ValueError, self._makeOne, request, max_age='invalid value') + self.assertRaises( + ValueError, self._makeOne, request, max_age='invalid value' + ) def test_custom_salt(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1}), salt=b'f.') request.cookies['session'] = cookieval @@ -389,6 +422,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_salt_mismatch(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1}), salt=b'f.') request.cookies['session'] = cookieval @@ -397,24 +431,29 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_custom_hashalg(self): import time + request = testing.DummyRequest() - cookieval = self._serialize((time.time(), 0, {'state': 1}), - hashalg='sha1') + cookieval = self._serialize( + (time.time(), 0, {'state': 1}), hashalg='sha1' + ) request.cookies['session'] = cookieval session = self._makeOne(request, hashalg='sha1') self.assertEqual(session['state'], 1) def test_hashalg_mismatch(self): import time + request = testing.DummyRequest() - cookieval = self._serialize((time.time(), 0, {'state': 1}), - hashalg='sha1') + cookieval = self._serialize( + (time.time(), 0, {'state': 1}), hashalg='sha1' + ) request.cookies['session'] = cookieval session = self._makeOne(request, hashalg='sha256') self.assertEqual(session, {}) def test_secret_mismatch(self): import time + request = testing.DummyRequest() cookieval = self._serialize((time.time(), 0, {'state': 1})) request.cookies['session'] = cookieval @@ -426,6 +465,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): from hashlib import sha512 import hmac import time + request = testing.DummyRequest() serializer = DummySerializer() cstruct = serializer.dumps((time.time(), 0, {'state': 1})) @@ -438,6 +478,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_invalid_data_size(self): from hashlib import sha512 import base64 + request = testing.DummyRequest() num_bytes = sha512().digest_size - 1 cookieval = base64.b64encode(b' ' * num_bytes) @@ -448,6 +489,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_very_long_key(self): verylongkey = b'a' * 1024 import webob + request = testing.DummyRequest() session = self._makeOne(request, secret=verylongkey) session['a'] = 1 @@ -457,7 +499,7 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): try: result = callbacks[0](request, response) - except TypeError: # pragma: no cover + except TypeError: # pragma: no cover self.fail('HMAC failed to initialize due to key length.') self.assertEqual(result, None) @@ -481,19 +523,25 @@ class TestSignedCookieSession(SharedCookieSessionTests, unittest.TestCase): session = self._makeOne(request, secret='secret') self.assertEqual(session, {}) -class TestUnencryptedCookieSession(SharedCookieSessionTests, unittest.TestCase): + +class TestUnencryptedCookieSession( + SharedCookieSessionTests, unittest.TestCase +): def setUp(self): super(TestUnencryptedCookieSession, self).setUp() from zope.deprecation import __show__ + __show__.off() def tearDown(self): super(TestUnencryptedCookieSession, self).tearDown() from zope.deprecation import __show__ + __show__.on() - + def _makeOne(self, request, **kw): from pyramid.session import UnencryptedCookieSessionFactoryConfig + self._rename_cookie_var(kw, 'path', 'cookie_path') self._rename_cookie_var(kw, 'domain', 'cookie_domain') self._rename_cookie_var(kw, 'secure', 'cookie_secure') @@ -508,20 +556,24 @@ class TestUnencryptedCookieSession(SharedCookieSessionTests, unittest.TestCase): def _serialize(self, value): from pyramid.compat import bytes_ from pyramid.session import signed_serialize + return bytes_(signed_serialize(value, 'secret')) def test_serialize_option(self): from pyramid.response import Response + secret = 'secret' request = testing.DummyRequest() - session = self._makeOne(request, - signed_serialize=dummy_signed_serialize) + session = self._makeOne( + request, signed_serialize=dummy_signed_serialize + ) session['key'] = 'value' response = Response() self.assertEqual(session._set_cookie(response), True) cookie = response.headerlist[-1][1] expected_cookieval = dummy_signed_serialize( - (session.accessed, session.created, {'key': 'value'}), secret) + (session.accessed, session.created, {'key': 'value'}), secret + ) response = Response() response.set_cookie('session', expected_cookieval, samesite='Lax') expected_cookie = response.headerlist[-1][1] @@ -529,32 +581,41 @@ class TestUnencryptedCookieSession(SharedCookieSessionTests, unittest.TestCase): def test_deserialize_option(self): import time + secret = 'secret' request = testing.DummyRequest() accessed = time.time() state = {'key': 'value'} cookieval = dummy_signed_serialize((accessed, accessed, state), secret) request.cookies['session'] = cookieval - session = self._makeOne(request, - signed_deserialize=dummy_signed_deserialize) + session = self._makeOne( + request, signed_deserialize=dummy_signed_deserialize + ) self.assertEqual(dict(session), state) + def dummy_signed_serialize(data, secret): import base64 from pyramid.compat import pickle, bytes_ + pickled = pickle.dumps(data) return base64.b64encode(bytes_(secret)) + base64.b64encode(pickled) + def dummy_signed_deserialize(serialized, secret): import base64 from pyramid.compat import pickle, bytes_ + serialized_data = base64.b64decode( - serialized[len(base64.b64encode(bytes_(secret))):]) + serialized[len(base64.b64encode(bytes_(secret))) :] + ) return pickle.loads(serialized_data) + class Test_manage_accessed(unittest.TestCase): def _makeOne(self, wrapped): from pyramid.session import manage_accessed + return manage_accessed(wrapped) def test_accessed_set(self): @@ -568,6 +629,7 @@ class Test_manage_accessed(unittest.TestCase): def test_accessed_without_renew(self): import time + request = testing.DummyRequest() session = DummySessionFactory(request) session._reissue_time = 5 @@ -588,11 +650,14 @@ class Test_manage_accessed(unittest.TestCase): result = wrapper(session, 'a') self.assertEqual(result, 1) callbacks = request.response_callbacks - if callbacks is not None: self.assertEqual(len(callbacks), 0) + if callbacks is not None: + self.assertEqual(len(callbacks), 0) + class Test_manage_changed(unittest.TestCase): def _makeOne(self, wrapped): from pyramid.session import manage_changed + return manage_changed(wrapped) def test_it(self): @@ -603,6 +668,7 @@ class Test_manage_changed(unittest.TestCase): self.assertNotEqual(session.accessed, None) self.assertTrue(session._dirty) + def serialize(data, secret): import hmac import base64 @@ -610,13 +676,16 @@ def serialize(data, secret): from pyramid.compat import bytes_ from pyramid.compat import native_ from pyramid.compat import pickle + pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) sig = hmac.new(bytes_(secret, 'utf-8'), pickled, sha1).hexdigest() return sig + native_(base64.b64encode(pickled)) + class Test_signed_serialize(unittest.TestCase): def _callFUT(self, data, secret): from pyramid.session import signed_serialize + return signed_serialize(data, secret) def test_it(self): @@ -635,12 +704,14 @@ class Test_signed_serialize(unittest.TestCase): expected = serialize('123', secret) result = self._callFUT('123', secret.decode('latin-1')) self.assertEqual(result, expected) - + + class Test_signed_deserialize(unittest.TestCase): def _callFUT(self, serialized, secret, hmac=None): if hmac is None: import hmac from pyramid.session import signed_deserialize + return signed_deserialize(serialized, secret, hmac=hmac) def test_it(self): @@ -656,12 +727,15 @@ class Test_signed_deserialize(unittest.TestCase): class hmac(object): def new(self, *arg): return self + def hexdigest(self): return '1234' + serialized = serialize('123', 'secret123') - self.assertRaises(ValueError, self._callFUT, serialized, 'secret', - hmac=hmac()) - + self.assertRaises( + ValueError, self._callFUT, serialized, 'secret', hmac=hmac() + ) + def test_it_bad_encoding(self): serialized = 'bad' + serialize('123', 'secret') self.assertRaises(ValueError, self._callFUT, serialized, 'secret') @@ -683,6 +757,7 @@ class Test_signed_deserialize(unittest.TestCase): class TestPickleSerializer(unittest.TestCase): def _makeOne(self): from pyramid.session import PickleSerializer + return PickleSerializer() def test_loads(self): @@ -731,6 +806,7 @@ class DummySerializer(object): except TypeError: raise ValueError + class DummySessionFactory(dict): _dirty = False _cookie_name = 'session' @@ -749,6 +825,7 @@ class DummySessionFactory(dict): def changed(self): self._dirty = True + class DummyResponse(object): def __init__(self): self.headerlist = [] diff --git a/tests/test_settings.py b/tests/test_settings.py index a586cb6fd..e8be490ee 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,18 +1,20 @@ import unittest + class Test_asbool(unittest.TestCase): def _callFUT(self, s): from pyramid.settings import asbool + return asbool(s) def test_s_is_None(self): result = self._callFUT(None) self.assertEqual(result, False) - + def test_s_is_True(self): result = self._callFUT(True) self.assertEqual(result, True) - + def test_s_is_False(self): result = self._callFUT(False) self.assertEqual(result, False) @@ -37,15 +39,17 @@ class Test_asbool(unittest.TestCase): result = self._callFUT(1) self.assertEqual(result, True) + class Test_aslist_cronly(unittest.TestCase): def _callFUT(self, val): from pyramid.settings import aslist_cronly + return aslist_cronly(val) def test_with_list(self): result = self._callFUT(['abc', 'def']) self.assertEqual(result, ['abc', 'def']) - + def test_with_string(self): result = self._callFUT('abc def') self.assertEqual(result, ['abc def']) @@ -54,15 +58,17 @@ class Test_aslist_cronly(unittest.TestCase): result = self._callFUT(' abc\n def') self.assertEqual(result, ['abc', 'def']) + class Test_aslist(unittest.TestCase): def _callFUT(self, val, **kw): from pyramid.settings import aslist + return aslist(val, **kw) def test_with_list(self): result = self._callFUT(['abc', 'def']) self.assertEqual(list(result), ['abc', 'def']) - + def test_with_string(self): result = self._callFUT('abc def') self.assertEqual(result, ['abc', 'def']) diff --git a/tests/test_static.py b/tests/test_static.py index f34f8f943..a323b1d89 100644 --- a/tests/test_static.py +++ b/tests/test_static.py @@ -5,11 +5,13 @@ import unittest here = os.path.dirname(__file__) # 5 years from now (more or less) -fiveyrsfuture = datetime.datetime.utcnow() + datetime.timedelta(5*365) +fiveyrsfuture = datetime.datetime.utcnow() + datetime.timedelta(5 * 365) + class Test_static_view_use_subpath_False(unittest.TestCase): def _getTargetClass(self): from pyramid.static import static_view + return static_view def _makeOne(self, *arg, **kw): @@ -17,15 +19,16 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def _makeRequest(self, kw=None): from pyramid.request import Request + environ = { - 'wsgi.url_scheme':'http', - 'wsgi.version':(1,0), - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'6543', - 'PATH_INFO':'/', - 'SCRIPT_NAME':'', - 'REQUEST_METHOD':'GET', - } + 'wsgi.url_scheme': 'http', + 'wsgi.version': (1, 0), + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '6543', + 'PATH_INFO': '/', + 'SCRIPT_NAME': '', + 'REQUEST_METHOD': 'GET', + } if kw is not None: environ.update(kw) return Request(environ=environ) @@ -39,9 +42,10 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_call_adds_slash_path_info_empty(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':''}) + request = self._makeRequest({'PATH_INFO': ''}) context = DummyContext() from pyramid.httpexceptions import HTTPMovedPermanently + self.assertRaises(HTTPMovedPermanently, inst, context, request) def test_path_info_slash_means_index_html(self): @@ -53,7 +57,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_oob_singledot(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/./index.html'}) + request = self._makeRequest({'PATH_INFO': '/./index.html'}) context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') @@ -61,7 +65,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_oob_emptyelement(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'//index.html'}) + request = self._makeRequest({'PATH_INFO': '//index.html'}) context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') @@ -69,58 +73,68 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_oob_dotdotslash(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/subdir/../../minimal.pt'}) + request = self._makeRequest({'PATH_INFO': '/subdir/../../minimal.pt'}) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_dotdotslash_encoded(self): inst = self._makeOne('tests:fixtures/static') request = self._makeRequest( - {'PATH_INFO':'/subdir/%2E%2E%2F%2E%2E/minimal.pt'}) + {'PATH_INFO': '/subdir/%2E%2E%2F%2E%2E/minimal.pt'} + ) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_os_sep(self): import os + inst = self._makeOne('tests:fixtures/static') dds = '..' + os.sep - request = self._makeRequest({'PATH_INFO':'/subdir/%s%sminimal.pt' % - (dds, dds)}) + request = self._makeRequest( + {'PATH_INFO': '/subdir/%s%sminimal.pt' % (dds, dds)} + ) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_resource_doesnt_exist(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/notthere'}) + request = self._makeRequest({'PATH_INFO': '/notthere'}) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_resource_isdir(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/subdir/'}) + request = self._makeRequest({'PATH_INFO': '/subdir/'}) context = DummyContext() response = inst(context, request) self.assertTrue(b'<html>subdir</html>' in response.body) def test_resource_is_file(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/index.html'}) + request = self._makeRequest({'PATH_INFO': '/index.html'}) context = DummyContext() response = inst(context, request) self.assertTrue(b'<html>static</html>' in response.body) def test_resource_is_file_with_wsgi_file_wrapper(self): from pyramid.response import _BLOCK_SIZE + inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/index.html'}) + request = self._makeRequest({'PATH_INFO': '/index.html'}) + class _Wrapper(object): def __init__(self, file, block_size=None): self.file = file self.block_size = block_size + request.environ['wsgi.file_wrapper'] = _Wrapper context = DummyContext() response = inst(context, request) @@ -132,34 +146,40 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_resource_is_file_with_cache_max_age(self): inst = self._makeOne('tests:fixtures/static', cache_max_age=600) - request = self._makeRequest({'PATH_INFO':'/index.html'}) + request = self._makeRequest({'PATH_INFO': '/index.html'}) context = DummyContext() response = inst(context, request) self.assertTrue(b'<html>static</html>' in response.body) self.assertEqual(len(response.headerlist), 5) - header_names = [ x[0] for x in response.headerlist ] + header_names = [x[0] for x in response.headerlist] header_names.sort() - self.assertEqual(header_names, - ['Cache-Control', 'Content-Length', 'Content-Type', - 'Expires', 'Last-Modified']) + self.assertEqual( + header_names, + [ + 'Cache-Control', + 'Content-Length', + 'Content-Type', + 'Expires', + 'Last-Modified', + ], + ) def test_resource_is_file_with_no_cache_max_age(self): - inst = self._makeOne('tests:fixtures/static', - cache_max_age=None) - request = self._makeRequest({'PATH_INFO':'/index.html'}) + inst = self._makeOne('tests:fixtures/static', cache_max_age=None) + request = self._makeRequest({'PATH_INFO': '/index.html'}) context = DummyContext() response = inst(context, request) self.assertTrue(b'<html>static</html>' in response.body) self.assertEqual(len(response.headerlist), 3) - header_names = [ x[0] for x in response.headerlist ] + header_names = [x[0] for x in response.headerlist] header_names.sort() self.assertEqual( - header_names, - ['Content-Length', 'Content-Type', 'Last-Modified']) + header_names, ['Content-Length', 'Content-Type', 'Last-Modified'] + ) def test_resource_notmodified(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/index.html'}) + request = self._makeRequest({'PATH_INFO': '/index.html'}) request.if_modified_since = fiveyrsfuture context = DummyContext() response = inst(context, request) @@ -173,14 +193,15 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_not_found(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/notthere.html'}) + request = self._makeRequest({'PATH_INFO': '/notthere.html'}) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_gz_resource_no_content_encoding(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/arcs.svg.tgz'}) + request = self._makeRequest({'PATH_INFO': '/arcs.svg.tgz'}) context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') @@ -190,7 +211,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): def test_resource_no_content_encoding(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':'/index.html'}) + request = self._makeRequest({'PATH_INFO': '/index.html'}) context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') @@ -198,9 +219,11 @@ class Test_static_view_use_subpath_False(unittest.TestCase): self.assertEqual(response.content_encoding, None) response.app_iter.close() + class Test_static_view_use_subpath_True(unittest.TestCase): def _getTargetClass(self): from pyramid.static import static_view + return static_view def _makeOne(self, *arg, **kw): @@ -209,15 +232,16 @@ class Test_static_view_use_subpath_True(unittest.TestCase): def _makeRequest(self, kw=None): from pyramid.request import Request + environ = { - 'wsgi.url_scheme':'http', - 'wsgi.version':(1,0), - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'6543', - 'PATH_INFO':'/', - 'SCRIPT_NAME':'', - 'REQUEST_METHOD':'GET', - } + 'wsgi.url_scheme': 'http', + 'wsgi.version': (1, 0), + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '6543', + 'PATH_INFO': '/', + 'SCRIPT_NAME': '', + 'REQUEST_METHOD': 'GET', + } if kw is not None: environ.update(kw) return Request(environ=environ) @@ -231,10 +255,11 @@ class Test_static_view_use_subpath_True(unittest.TestCase): def test_call_adds_slash_path_info_empty(self): inst = self._makeOne('tests:fixtures/static') - request = self._makeRequest({'PATH_INFO':''}) + request = self._makeRequest({'PATH_INFO': ''}) request.subpath = () context = DummyContext() from pyramid.httpexceptions import HTTPMovedPermanently + self.assertRaises(HTTPMovedPermanently, inst, context, request) def test_path_info_slash_means_index_html(self): @@ -251,6 +276,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('.', 'index.html') context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_emptyelement(self): @@ -259,6 +285,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('', 'index.html') context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_dotdotslash(self): @@ -267,6 +294,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('subdir', '..', '..', 'minimal.pt') context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_dotdotslash_encoded(self): @@ -275,24 +303,28 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('subdir', '%2E%2E', '%2E%2E', 'minimal.pt') context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_oob_os_sep(self): import os + inst = self._makeOne('tests:fixtures/static') dds = '..' + os.sep request = self._makeRequest() request.subpath = ('subdir', dds, dds, 'minimal.pt') context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_resource_doesnt_exist(self): inst = self._makeOne('tests:fixtures/static') request = self._makeRequest() - request.subpath = ('notthere,') + request.subpath = 'notthere,' context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) def test_resource_isdir(self): @@ -319,26 +351,32 @@ class Test_static_view_use_subpath_True(unittest.TestCase): response = inst(context, request) self.assertTrue(b'<html>static</html>' in response.body) self.assertEqual(len(response.headerlist), 5) - header_names = [ x[0] for x in response.headerlist ] + header_names = [x[0] for x in response.headerlist] header_names.sort() - self.assertEqual(header_names, - ['Cache-Control', 'Content-Length', 'Content-Type', - 'Expires', 'Last-Modified']) + self.assertEqual( + header_names, + [ + 'Cache-Control', + 'Content-Length', + 'Content-Type', + 'Expires', + 'Last-Modified', + ], + ) def test_resource_is_file_with_no_cache_max_age(self): - inst = self._makeOne('tests:fixtures/static', - cache_max_age=None) + inst = self._makeOne('tests:fixtures/static', cache_max_age=None) request = self._makeRequest() request.subpath = ('index.html',) context = DummyContext() response = inst(context, request) self.assertTrue(b'<html>static</html>' in response.body) self.assertEqual(len(response.headerlist), 3) - header_names = [ x[0] for x in response.headerlist ] + header_names = [x[0] for x in response.headerlist] header_names.sort() self.assertEqual( - header_names, - ['Content-Length', 'Content-Type', 'Last-Modified']) + header_names, ['Content-Length', 'Content-Type', 'Last-Modified'] + ) def test_resource_notmodified(self): inst = self._makeOne('tests:fixtures/static') @@ -361,12 +399,14 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('notthere.html',) context = DummyContext() from pyramid.httpexceptions import HTTPNotFound + self.assertRaises(HTTPNotFound, inst, context, request) -class TestQueryStringConstantCacheBuster(unittest.TestCase): +class TestQueryStringConstantCacheBuster(unittest.TestCase): def _makeOne(self, param=None): from pyramid.static import QueryStringConstantCacheBuster as cls + if param: inst = cls('foo', param) else: @@ -380,31 +420,34 @@ class TestQueryStringConstantCacheBuster(unittest.TestCase): def test_it(self): fut = self._makeOne() self.assertEqual( - fut('foo', 'bar', {}), - ('bar', {'_query': {'x': 'foo'}})) + fut('foo', 'bar', {}), ('bar', {'_query': {'x': 'foo'}}) + ) def test_change_param(self): fut = self._makeOne('y') self.assertEqual( - fut('foo', 'bar', {}), - ('bar', {'_query': {'y': 'foo'}})) + fut('foo', 'bar', {}), ('bar', {'_query': {'y': 'foo'}}) + ) def test_query_is_already_tuples(self): fut = self._makeOne() self.assertEqual( fut('foo', 'bar', {'_query': [('a', 'b')]}), - ('bar', {'_query': (('a', 'b'), ('x', 'foo'))})) + ('bar', {'_query': (('a', 'b'), ('x', 'foo'))}), + ) def test_query_is_tuple_of_tuples(self): fut = self._makeOne() self.assertEqual( fut('foo', 'bar', {'_query': (('a', 'b'),)}), - ('bar', {'_query': (('a', 'b'), ('x', 'foo'))})) + ('bar', {'_query': (('a', 'b'), ('x', 'foo'))}), + ) -class TestManifestCacheBuster(unittest.TestCase): +class TestManifestCacheBuster(unittest.TestCase): def _makeOne(self, path, **kw): from pyramid.static import ManifestCacheBuster as cls + return cls(path, **kw) def test_it(self): @@ -412,22 +455,22 @@ class TestManifestCacheBuster(unittest.TestCase): fut = self._makeOne(manifest_path) self.assertEqual(fut('foo', 'bar', {}), ('bar', {})) self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-test.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-test.css', {}) + ) def test_it_with_relspec(self): fut = self._makeOne('fixtures/manifest.json') self.assertEqual(fut('foo', 'bar', {}), ('bar', {})) self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-test.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-test.css', {}) + ) def test_it_with_absspec(self): fut = self._makeOne('tests:fixtures/manifest.json') self.assertEqual(fut('foo', 'bar', {}), ('bar', {})) self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-test.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-test.css', {}) + ) def test_reload(self): manifest_path = os.path.join(here, 'fixtures', 'manifest.json') @@ -437,27 +480,25 @@ class TestManifestCacheBuster(unittest.TestCase): fut = inst # test without a valid manifest - self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main.css', {})) + self.assertEqual(fut('foo', 'css/main.css', {}), ('css/main.css', {})) # swap to a real manifest, setting mtime to 0 inst.manifest_path = manifest_path self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-test.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-test.css', {}) + ) # ensure switching the path doesn't change the result inst.manifest_path = new_manifest_path self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-test.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-test.css', {}) + ) # update mtime, should cause a reload inst.getmtime = lambda *args, **kwargs: 1 self.assertEqual( - fut('foo', 'css/main.css', {}), - ('css/main-678b7c80.css', {})) + fut('foo', 'css/main.css', {}), ('css/main-678b7c80.css', {}) + ) def test_invalid_manifest(self): self.assertRaises(IOError, lambda: self._makeOne('foo')) @@ -466,12 +507,15 @@ class TestManifestCacheBuster(unittest.TestCase): inst = self._makeOne('foo', reload=True) self.assertEqual(inst.manifest, {}) + class DummyContext: pass + class DummyStartResponse: status = () headers = () + def __call__(self, status, headers): self.status = status self.headers = headers diff --git a/tests/test_testing.py b/tests/test_testing.py index 51ffb9822..b5c689794 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -2,19 +2,23 @@ import unittest from zope.component import getSiteManager from pyramid import testing + class TestDummyRootFactory(unittest.TestCase): def _makeOne(self, environ): from pyramid.testing import DummyRootFactory + return DummyRootFactory(environ) def test_it(self): - environ = {'bfg.routes.matchdict':{'a':1}} + environ = {'bfg.routes.matchdict': {'a': 1}} factory = self._makeOne(environ) self.assertEqual(factory.a, 1) + class TestDummySecurityPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.testing import DummySecurityPolicy + return DummySecurityPolicy def _makeOne(self, userid=None, groupids=(), permissive=True): @@ -33,47 +37,55 @@ class TestDummySecurityPolicy(unittest.TestCase): policy = self._makeOne('user', ('group1',)) from pyramid.security import Everyone from pyramid.security import Authenticated - self.assertEqual(policy.effective_principals(None), - [Everyone, Authenticated, 'user', 'group1']) + + self.assertEqual( + policy.effective_principals(None), + [Everyone, Authenticated, 'user', 'group1'], + ) def test_effective_principals_nouserid(self): policy = self._makeOne() from pyramid.security import Everyone + self.assertEqual(policy.effective_principals(None), [Everyone]) def test_permits(self): policy = self._makeOne() self.assertEqual(policy.permits(None, None, None), True) - + def test_principals_allowed_by_permission(self): policy = self._makeOne('user', ('group1',)) from pyramid.security import Everyone from pyramid.security import Authenticated + result = policy.principals_allowed_by_permission(None, None) self.assertEqual(result, [Everyone, Authenticated, 'user', 'group1']) def test_forget(self): policy = self._makeOne() self.assertEqual(policy.forget(None), []) - + def test_remember(self): policy = self._makeOne() self.assertEqual(policy.remember(None, None), []) - - + class TestDummyResource(unittest.TestCase): def _getTargetClass(self): from pyramid.testing import DummyResource + return DummyResource def _makeOne(self, name=None, parent=None, **kw): klass = self._getTargetClass() return klass(name, parent, **kw) - def test__setitem__and__getitem__and__delitem__and__contains__and_get(self): + def test__setitem__and__getitem__and__delitem__and__contains__and_get( + self + ): class Dummy: pass + dummy = Dummy() resource = self._makeOne() resource['abc'] = dummy @@ -91,7 +103,7 @@ class TestDummyResource(unittest.TestCase): def test_extra_params(self): resource = self._makeOne(foo=1) self.assertEqual(resource.foo, 1) - + def test_clone(self): resource = self._makeOne('name', 'parent', foo=1, bar=2) clone = resource.clone('name2', 'parent2', bar=1) @@ -103,6 +115,7 @@ class TestDummyResource(unittest.TestCase): def test_keys_items_values_len(self): class Dummy: pass + resource = self._makeOne() resource['abc'] = Dummy() resource['def'] = Dummy() @@ -119,24 +132,27 @@ class TestDummyResource(unittest.TestCase): def test_bool(self): resource = self._makeOne() self.assertEqual(resource.__bool__(), True) - + def test_ctor_with__provides__(self): resource = self._makeOne(__provides__=IDummy) self.assertTrue(IDummy.providedBy(resource)) + class TestDummyRequest(unittest.TestCase): def _getTargetClass(self): from pyramid.testing import DummyRequest + return DummyRequest def _makeOne(self, *arg, **kw): return self._getTargetClass()(*arg, **kw) def test_params(self): - request = self._makeOne(params = {'say':'Hello'}, - environ = {'PATH_INFO':'/foo'}, - headers = {'X-Foo':'YUP'}, - ) + request = self._makeOne( + params={'say': 'Hello'}, + environ={'PATH_INFO': '/foo'}, + headers={'X-Foo': 'YUP'}, + ) self.assertEqual(request.params['say'], 'Hello') self.assertEqual(request.GET['say'], 'Hello') self.assertEqual(request.POST['say'], 'Hello') @@ -146,6 +162,7 @@ class TestDummyRequest(unittest.TestCase): def test_defaults(self): from pyramid.threadlocal import get_current_registry from pyramid.testing import DummySession + request = self._makeOne() self.assertEqual(request.method, 'GET') self.assertEqual(request.application_url, 'http://example.com') @@ -174,25 +191,25 @@ class TestDummyRequest(unittest.TestCase): self.assertEqual(request.session.__class__, DummySession) def test_params_explicit(self): - request = self._makeOne(params = {'foo':'bar'}) + request = self._makeOne(params={'foo': 'bar'}) self.assertEqual(request.params['foo'], 'bar') self.assertEqual(request.GET['foo'], 'bar') self.assertEqual(request.POST['foo'], 'bar') def test_environ_explicit(self): - request = self._makeOne(environ = {'PATH_INFO':'/foo'}) + request = self._makeOne(environ={'PATH_INFO': '/foo'}) self.assertEqual(request.environ['PATH_INFO'], '/foo') def test_headers_explicit(self): - request = self._makeOne(headers = {'X-Foo':'YUP'}) + request = self._makeOne(headers={'X-Foo': 'YUP'}) self.assertEqual(request.headers['X-Foo'], 'YUP') def test_path_explicit(self): - request = self._makeOne(path = '/abc') + request = self._makeOne(path='/abc') self.assertEqual(request.path, '/abc') def test_cookies_explicit(self): - request = self._makeOne(cookies = {'type': 'gingersnap'}) + request = self._makeOne(cookies={'type': 'gingersnap'}) self.assertEqual(request.cookies['type'], 'gingersnap') def test_post_explicit(self): @@ -213,7 +230,7 @@ class TestDummyRequest(unittest.TestCase): self.assertEqual(request.POST.get('foo'), None) def test_kwargs(self): - request = self._makeOne(water = 1) + request = self._makeOne(water=1) self.assertEqual(request.water, 1) def test_add_response_callback(self): @@ -225,6 +242,7 @@ class TestDummyRequest(unittest.TestCase): # see https://github.com/Pylons/pyramid/issues/165 from pyramid.registry import Registry from pyramid.config import Configurator + request = self._makeOne() try: registry = Registry('this_test') @@ -243,6 +261,7 @@ class TestDummyRequest(unittest.TestCase): # see https://github.com/Pylons/pyramid/issues/165 from pyramid.registry import Registry from pyramid.config import Configurator + request = self._makeOne() request.registry = 'abc' self.assertEqual(request.registry, 'abc') @@ -258,32 +277,35 @@ class TestDummyRequest(unittest.TestCase): def test_response_with_responsefactory(self): from pyramid.registry import Registry from pyramid.interfaces import IResponseFactory + registry = Registry('this_test') + class ResponseFactory(object): pass - registry.registerUtility( - lambda r: ResponseFactory(), IResponseFactory - ) + + registry.registerUtility(lambda r: ResponseFactory(), IResponseFactory) request = self._makeOne() request.registry = registry resp = request.response self.assertEqual(resp.__class__, ResponseFactory) - self.assertTrue(request.response is resp) # reified + self.assertTrue(request.response is resp) # reified def test_response_without_responsefactory(self): from pyramid.registry import Registry from pyramid.response import Response + registry = Registry('this_test') request = self._makeOne() request.registry = registry resp = request.response self.assertEqual(resp.__class__, Response) - self.assertTrue(request.response is resp) # reified - + self.assertTrue(request.response is resp) # reified + class TestDummyTemplateRenderer(unittest.TestCase): - def _getTargetClass(self, ): + def _getTargetClass(self,): from pyramid.testing import DummyTemplateRenderer + return DummyTemplateRenderer def _makeOne(self, string_response=''): @@ -298,29 +320,32 @@ class TestDummyTemplateRenderer(unittest.TestCase): def test_getattr(self): renderer = self._makeOne() - renderer({'a':1}) + renderer({'a': 1}) self.assertEqual(renderer.a, 1) self.assertRaises(AttributeError, renderer.__getattr__, 'b') def test_assert_(self): renderer = self._makeOne() - renderer({'a':1, 'b':2}) + renderer({'a': 1, 'b': 2}) self.assertRaises(AssertionError, renderer.assert_, c=1) self.assertRaises(AssertionError, renderer.assert_, b=3) self.assertTrue(renderer.assert_(a=1, b=2)) - + def test_nondefault_string_response(self): renderer = self._makeOne('abc') - result = renderer({'a':1, 'b':2}) + result = renderer({'a': 1, 'b': 2}) self.assertEqual(result, 'abc') + class Test_setUp(unittest.TestCase): def _callFUT(self, **kw): from pyramid.testing import setUp + return setUp(**kw) def tearDown(self): from pyramid.threadlocal import manager + manager.clear() getSiteManager.reset() @@ -332,6 +357,7 @@ class Test_setUp(unittest.TestCase): from pyramid.threadlocal import manager from pyramid.threadlocal import get_current_registry from pyramid.registry import Registry + old = True manager.push(old) config = self._callFUT() @@ -346,13 +372,15 @@ class Test_setUp(unittest.TestCase): def test_it_with_registry(self): from pyramid.registry import Registry from pyramid.threadlocal import manager + registry = Registry() self._callFUT(registry=registry) current = manager.get() self.assertEqual(current['registry'], registry) - + def test_it_with_request(self): from pyramid.threadlocal import manager + request = object() self._callFUT(request=request) current = manager.get() @@ -364,6 +392,7 @@ class Test_setUp(unittest.TestCase): def test_it_with_hook_zca_false(self): from pyramid.registry import Registry + registry = Registry() self._callFUT(registry=registry, hook_zca=False) sm = getSiteManager() @@ -371,26 +400,32 @@ class Test_setUp(unittest.TestCase): def test_it_with_settings_passed_explicit_registry(self): from pyramid.registry import Registry + registry = Registry() self._callFUT(registry=registry, hook_zca=False, settings=dict(a=1)) self.assertEqual(registry.settings['a'], 1) - + def test_it_with_settings_passed_implicit_registry(self): config = self._callFUT(hook_zca=False, settings=dict(a=1)) self.assertEqual(config.registry.settings['a'], 1) + class Test_cleanUp(Test_setUp): def _callFUT(self, *arg, **kw): from pyramid.testing import cleanUp + return cleanUp(*arg, **kw) - + + class Test_tearDown(unittest.TestCase): def _callFUT(self, **kw): from pyramid.testing import tearDown + return tearDown(**kw) def tearDown(self): from pyramid.threadlocal import manager + manager.clear() getSiteManager.reset() @@ -403,8 +438,9 @@ class Test_tearDown(unittest.TestCase): def test_defaults(self): from pyramid.threadlocal import manager + registry = DummyRegistry() - old = {'registry':registry} + old = {'registry': registry} hook = lambda *arg: None try: self._setSMHook(hook) @@ -419,14 +455,17 @@ class Test_tearDown(unittest.TestCase): def test_registry_cannot_be_inited(self): from pyramid.threadlocal import manager + registry = DummyRegistry() + def raiseit(name): raise TypeError + registry.__init__ = raiseit - old = {'registry':registry} + old = {'registry': registry} try: manager.push(old) - self._callFUT() # doesn't blow up + self._callFUT() # doesn't blow up current = manager.get() self.assertNotEqual(current, old) self.assertEqual(registry.inited, 1) @@ -441,9 +480,11 @@ class Test_tearDown(unittest.TestCase): finally: self._assertSMHook(hook) + class TestDummyRendererFactory(unittest.TestCase): def _makeOne(self, name, factory): from pyramid.testing import DummyRendererFactory + return DummyRendererFactory(name, factory) def test_add_no_colon(self): @@ -460,30 +501,33 @@ class TestDummyRendererFactory(unittest.TestCase): def test_call(self): f = self._makeOne('name', None) f.renderers['spec'] = 'renderer' - info = DummyRendererInfo({'name':'spec'}) + info = DummyRendererInfo({'name': 'spec'}) self.assertEqual(f(info), 'renderer') - + def test_call2(self): f = self._makeOne('name', None) f.renderers['spec'] = 'renderer' - info = DummyRendererInfo({'name':'spec:spec'}) + info = DummyRendererInfo({'name': 'spec:spec'}) self.assertEqual(f(info), 'renderer') def test_call3(self): def factory(spec): return 'renderer' + f = self._makeOne('name', factory) - info = DummyRendererInfo({'name':'spec'}) + info = DummyRendererInfo({'name': 'spec'}) self.assertEqual(f(info), 'renderer') def test_call_miss(self): f = self._makeOne('name', None) - info = DummyRendererInfo({'name':'spec'}) + info = DummyRendererInfo({'name': 'spec'}) self.assertRaises(KeyError, f, info) + class TestMockTemplate(unittest.TestCase): def _makeOne(self, response): from pyramid.testing import MockTemplate + return MockTemplate(response) def test_getattr(self): @@ -498,39 +542,52 @@ class TestMockTemplate(unittest.TestCase): template = self._makeOne('123') self.assertEqual(template(), '123') + class Test_skip_on(unittest.TestCase): def setUp(self): from pyramid.testing import skip_on + self.os_name = skip_on.os_name skip_on.os_name = 'wrong' def tearDown(self): from pyramid.testing import skip_on + skip_on.os_name = self.os_name - + def _callFUT(self, *platforms): from pyramid.testing import skip_on + return skip_on(*platforms) def test_wrong_platform(self): - def foo(): return True + def foo(): + return True + decorated = self._callFUT('wrong')(foo) self.assertEqual(decorated(), None) - + def test_ok_platform(self): - def foo(): return True + def foo(): + return True + decorated = self._callFUT('ok')(foo) self.assertEqual(decorated(), True) + class TestDummySession(unittest.TestCase): def _makeOne(self): from pyramid.testing import DummySession + return DummySession() - @testing.skip_on('pypy') # see https://github.com/Pylons/pyramid/issues/3237 + @testing.skip_on( + 'pypy' + ) # see https://github.com/Pylons/pyramid/issues/3237 def test_instance_conforms(self): from zope.interface.verify import verifyObject from pyramid.interfaces import ISession + session = self._makeOne() verifyObject(ISession, session) @@ -549,7 +606,7 @@ class TestDummySession(unittest.TestCase): session.flash('msg1') session.flash('msg2') self.assertEqual(session['_f_'], ['msg1', 'msg2']) - + def test_flash_mixed(self): session = self._makeOne() session.flash('warn1', 'warn') @@ -608,32 +665,39 @@ class TestDummySession(unittest.TestCase): self.assertNotEqual(token, None) self.assertTrue(len(token) >= 1) + from zope.interface import Interface from zope.interface import implementer - + + class IDummy(Interface): pass + @implementer(IDummy) class DummyEvent: pass - + + class DummyFactory: def __init__(self, environ): """ """ + class DummyRegistry(object): inited = 0 __name__ = 'name' + def __init__(self, name=''): self.inited = self.inited + 1 - + + class DummyRendererInfo(object): def __init__(self, kw): self.__dict__.update(kw) - -class Test_testConfig(unittest.TestCase): + +class Test_testConfig(unittest.TestCase): def _setUp(self, **kw): self._log.append(('setUp', kw)) return 'fake config' @@ -643,6 +707,7 @@ class Test_testConfig(unittest.TestCase): def setUp(self): from pyramid import testing + self._log = [] self._orig_setUp = testing.setUp testing.setUp = self._setUp @@ -651,39 +716,53 @@ class Test_testConfig(unittest.TestCase): def tearDown(self): from pyramid import testing + testing.setUp = self._orig_setUp testing.tearDown = self._orig_tearDown def _callFUT(self, inner, **kw): from pyramid.testing import testConfig + with testConfig(**kw) as config: inner(config) def test_ok_calls(self): self.assertEqual(self._log, []) + def inner(config): - self.assertEqual(self._log, - [('setUp', - {'autocommit': True, + self.assertEqual( + self._log, + [ + ( + 'setUp', + { + 'autocommit': True, 'hook_zca': True, 'registry': None, 'request': None, - 'settings': None})]) + 'settings': None, + }, + ) + ], + ) self._log.pop() + self._callFUT(inner) - self.assertEqual(self._log, - [('tearDown', {'unhook_zca': True})]) + self.assertEqual(self._log, [('tearDown', {'unhook_zca': True})]) def test_teardown_called_on_exception(self): class TestException(Exception): pass + def inner(config): self._log = [] raise TestException('oops') + self.assertRaises(TestException, self._callFUT, inner) self.assertEqual(self._log[0][0], 'tearDown') def test_ok_get_config(self): def inner(config): self.assertEqual(config, 'fake config') + self._callFUT(inner) diff --git a/tests/test_threadlocal.py b/tests/test_threadlocal.py index 088156507..487c7f4f2 100644 --- a/tests/test_threadlocal.py +++ b/tests/test_threadlocal.py @@ -1,6 +1,7 @@ from pyramid import testing import unittest + class TestThreadLocalManager(unittest.TestCase): def setUp(self): testing.setUp() @@ -10,6 +11,7 @@ class TestThreadLocalManager(unittest.TestCase): def _getTargetClass(self): from pyramid.threadlocal import ThreadLocalManager + return ThreadLocalManager def _makeOne(self, default=lambda *x: 1): @@ -23,6 +25,7 @@ class TestThreadLocalManager(unittest.TestCase): def test_default(self): def thedefault(): return '123' + local = self._makeOne(thedefault) self.assertEqual(local.stack, []) self.assertEqual(local.get(), '123') @@ -49,6 +52,7 @@ class TestThreadLocalManager(unittest.TestCase): class TestGetCurrentRequest(unittest.TestCase): def _callFUT(self): from pyramid.threadlocal import get_current_request + return get_current_request() def test_it_None(self): @@ -57,39 +61,45 @@ class TestGetCurrentRequest(unittest.TestCase): def test_it(self): from pyramid.threadlocal import manager + request = object() try: - manager.push({'request':request}) + manager.push({'request': request}) self.assertEqual(self._callFUT(), request) finally: manager.pop() self.assertEqual(self._callFUT(), None) + class GetCurrentRegistryTests(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() - + def _callFUT(self): from pyramid.threadlocal import get_current_registry + return get_current_registry() def test_it(self): from pyramid.threadlocal import manager + try: - manager.push({'registry':123}) + manager.push({'registry': 123}) self.assertEqual(self._callFUT(), 123) finally: manager.pop() + class GetCurrentRegistryWithoutTestingRegistry(unittest.TestCase): def _callFUT(self): from pyramid.threadlocal import get_current_registry + return get_current_registry() def test_it(self): from pyramid.registry import global_registry + self.assertEqual(self._callFUT(), global_registry) - diff --git a/tests/test_traversal.py b/tests/test_traversal.py index 437fe46df..8521844b0 100644 --- a/tests/test_traversal.py +++ b/tests/test_traversal.py @@ -3,17 +3,13 @@ import unittest from pyramid.testing import cleanUp -from pyramid.compat import ( - text_, - native_, - text_type, - url_quote, - PY2, - ) +from pyramid.compat import text_, native_, text_type, url_quote, PY2 + class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): from pyramid.traversal import traversal_path + return traversal_path(path) def test_utf8(self): @@ -26,6 +22,7 @@ class TraversalPathTests(unittest.TestCase): def test_utf16(self): from pyramid.exceptions import URLDecodeError + la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16') encoded = url_quote(la) path = '/'.join([encoded, encoded]) @@ -33,20 +30,26 @@ class TraversalPathTests(unittest.TestCase): def test_unicode_highorder_chars(self): path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') - self.assertEqual(self._callFUT(path), - (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),)) + self.assertEqual( + self._callFUT(path), + (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),), + ) def test_element_urllquoted(self): - self.assertEqual(self._callFUT('/foo/space%20thing/bar'), - (text_('foo'), text_('space thing'), text_('bar'))) + self.assertEqual( + self._callFUT('/foo/space%20thing/bar'), + (text_('foo'), text_('space thing'), text_('bar')), + ) def test_unicode_undecodeable_to_ascii(self): path = text_(b'/La Pe\xc3\xb1a', 'utf-8') self.assertRaises(UnicodeEncodeError, self._callFUT, path) + class TraversalPathInfoTests(unittest.TestCase): def _callFUT(self, path): from pyramid.traversal import traversal_path_info + return traversal_path_info(path) def test_path_startswith_endswith(self): @@ -56,8 +59,9 @@ class TraversalPathInfoTests(unittest.TestCase): self.assertEqual(self._callFUT('foo///'), (text_('foo'),)) def test_onedot(self): - self.assertEqual(self._callFUT('foo/./bar'), - (text_('foo'), text_('bar'))) + self.assertEqual( + self._callFUT('foo/./bar'), (text_('foo'), text_('bar')) + ) def test_twodots(self): self.assertEqual(self._callFUT('foo/../bar'), (text_('bar'),)) @@ -88,10 +92,12 @@ class TraversalPathInfoTests(unittest.TestCase): def test_highorder_undecodeable(self): from pyramid.exceptions import URLDecodeError + la = text_(b'La Pe\xc3\xb1a', 'utf-8') notlatin1 = native_(la) self.assertRaises(URLDecodeError, self._callFUT, notlatin1) + class ResourceTreeTraverserTests(unittest.TestCase): def setUp(self): cleanUp() @@ -101,6 +107,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): def _getTargetClass(self): from pyramid.traversal import ResourceTreeTraverser + return ResourceTreeTraverser def _makeOne(self, *arg, **kw): @@ -115,11 +122,13 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_class_conforms_to_ITraverser(self): from zope.interface.verify import verifyClass from pyramid.interfaces import ITraverser + verifyClass(ITraverser, self._getTargetClass()) def test_instance_conforms_to_ITraverser(self): from zope.interface.verify import verifyObject from pyramid.interfaces import ITraverser + context = DummyContext() verifyObject(ITraverser, self._makeOne(context)) @@ -249,12 +258,14 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], - (text_('foo'), text_('bar'), text_('baz'))) + self.assertEqual( + result['traversed'], (text_('foo'), text_('bar'), text_('baz')) + ) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], bar) - self.assertEqual(result['virtual_root_path'], - (text_('foo'), text_('bar'))) + self.assertEqual( + result['virtual_root_path'], (text_('foo'), text_('bar')) + ) def test_call_with_vh_root2(self): environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo') @@ -268,8 +279,9 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], - (text_('foo'), text_('bar'), text_('baz'))) + self.assertEqual( + result['traversed'], (text_('foo'), text_('bar'), text_('baz')) + ) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], foo) self.assertEqual(result['virtual_root_path'], (text_('foo'),)) @@ -286,8 +298,9 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], - (text_('foo'), text_('bar'), text_('baz'))) + self.assertEqual( + result['traversed'], (text_('foo'), text_('bar'), text_('baz')) + ) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], root) self.assertEqual(result['virtual_root_path'], ()) @@ -304,12 +317,15 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], - (text_('foo'), text_('bar'), text_('baz'))) + self.assertEqual( + result['traversed'], (text_('foo'), text_('bar'), text_('baz')) + ) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], baz) - self.assertEqual(result['virtual_root_path'], - (text_('foo'), text_('bar'), text_('baz'))) + self.assertEqual( + result['virtual_root_path'], + (text_('foo'), text_('bar'), text_('baz')), + ) def test_call_with_vh_root_path_root(self): policy = self._makeOne(None) @@ -340,19 +356,14 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], bar) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual( - result['traversed'], - (path, text_('bar')) - ) + self.assertEqual(result['traversed'], (path, text_('bar'))) self.assertEqual(result['root'], policy.root) self.assertEqual(result['virtual_root'], foo) - self.assertEqual( - result['virtual_root_path'], - (path,) - ) + self.assertEqual(result['virtual_root_path'], (path,)) def test_path_info_raises_unicodedecodeerror(self): from pyramid.exceptions import URLDecodeError + foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) @@ -379,13 +390,13 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_withroute_with_subpath_string(self): resource = DummyContext() traverser = self._makeOne(resource) - matchdict = {'subpath':'/a/b/c'} + matchdict = {'subpath': '/a/b/c'} request = DummyRequest({}) request.matchdict = matchdict result = traverser(request) self.assertEqual(result['context'], resource) self.assertEqual(result['view_name'], '') - self.assertEqual(result['subpath'], ('a', 'b','c')) + self.assertEqual(result['subpath'], ('a', 'b', 'c')) self.assertEqual(result['traversed'], ()) self.assertEqual(result['root'], resource) self.assertEqual(result['virtual_root'], resource) @@ -394,13 +405,13 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_withroute_with_subpath_tuple(self): resource = DummyContext() traverser = self._makeOne(resource) - matchdict = {'subpath':('a', 'b', 'c')} + matchdict = {'subpath': ('a', 'b', 'c')} request = DummyRequest({}) request.matchdict = matchdict result = traverser(request) self.assertEqual(result['context'], resource) self.assertEqual(result['view_name'], '') - self.assertEqual(result['subpath'], ('a', 'b','c')) + self.assertEqual(result['subpath'], ('a', 'b', 'c')) self.assertEqual(result['traversed'], ()) self.assertEqual(result['root'], resource) self.assertEqual(result['virtual_root'], resource) @@ -409,7 +420,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_withroute_and_traverse_string(self): resource = DummyContext() traverser = self._makeOne(resource) - matchdict = {'traverse':text_('foo/bar')} + matchdict = {'traverse': text_('foo/bar')} request = DummyRequest({}) request.matchdict = matchdict result = traverser(request) @@ -424,7 +435,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_withroute_and_traverse_tuple(self): resource = DummyContext() traverser = self._makeOne(resource) - matchdict = {'traverse':('foo', 'bar')} + matchdict = {'traverse': ('foo', 'bar')} request = DummyRequest({}) request.matchdict = matchdict result = traverser(request) @@ -439,7 +450,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): def test_withroute_and_traverse_empty(self): resource = DummyContext() traverser = self._makeOne(resource) - matchdict = {'traverse':''} + matchdict = {'traverse': ''} request = DummyRequest({}) request.matchdict = matchdict result = traverser(request) @@ -457,7 +468,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): environ = self._getEnviron(HTTP_X_VHM_ROOT='/abc') request = DummyRequest(environ) traverser = self._makeOne(resource) - matchdict = {'traverse':text_('/foo/bar')} + matchdict = {'traverse': text_('/foo/bar')} request.matchdict = matchdict result = traverser(request) self.assertEqual(result['context'], abc) @@ -467,10 +478,12 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['root'], resource) self.assertEqual(result['virtual_root'], abc) self.assertEqual(result['virtual_root_path'], ('abc',)) - + + class FindInterfaceTests(unittest.TestCase): def _callFUT(self, context, iface): from pyramid.traversal import find_interface + return find_interface(context, iface) def test_it_interface(self): @@ -488,8 +501,10 @@ class FindInterfaceTests(unittest.TestCase): baz.__name__ = 'baz' from zope.interface import directlyProvides from zope.interface import Interface + class IFoo(Interface): pass + directlyProvides(root, IFoo) result = self._callFUT(baz, IFoo) self.assertEqual(result.__name__, 'root') @@ -498,6 +513,7 @@ class FindInterfaceTests(unittest.TestCase): class DummyRoot(object): def __init__(self, child): self.child = child + baz = DummyContext() bar = DummyContext(baz) foo = DummyContext(bar) @@ -513,9 +529,11 @@ class FindInterfaceTests(unittest.TestCase): result = self._callFUT(baz, DummyRoot) self.assertEqual(result.__name__, 'root') + class FindRootTests(unittest.TestCase): def _callFUT(self, context): from pyramid.traversal import find_root + return find_root(context) def test_it(self): @@ -528,21 +546,25 @@ class FindRootTests(unittest.TestCase): result = self._callFUT(baz) self.assertEqual(result, dummy) + class FindResourceTests(unittest.TestCase): def _callFUT(self, context, name): from pyramid.traversal import find_resource + return find_resource(context, name) def _registerTraverser(self, traverser): from pyramid.threadlocal import get_current_registry + reg = get_current_registry() from pyramid.interfaces import ITraverser from zope.interface import Interface + reg.registerAdapter(traverser, (Interface,), ITraverser) def test_list(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, ['']) self.assertEqual(result, resource) @@ -550,17 +572,19 @@ class FindResourceTests(unittest.TestCase): def test_generator(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) + def foo(): yield '' + result = self._callFUT(resource, foo()) self.assertEqual(result, resource) self.assertEqual(resource.request.environ['PATH_INFO'], '/') def test_self_string_found(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, '') self.assertEqual(result, resource) @@ -568,7 +592,7 @@ class FindResourceTests(unittest.TestCase): def test_self_tuple_found(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, ()) self.assertEqual(result, resource) @@ -577,7 +601,7 @@ class FindResourceTests(unittest.TestCase): def test_relative_string_found(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':''}) + traverser = make_traverser({'context': baz, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, 'baz') self.assertEqual(result, baz) @@ -586,7 +610,7 @@ class FindResourceTests(unittest.TestCase): def test_relative_tuple_found(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':''}) + traverser = make_traverser({'context': baz, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, ('baz',)) self.assertEqual(result, baz) @@ -595,7 +619,7 @@ class FindResourceTests(unittest.TestCase): def test_relative_string_notfound(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':'bar'}) + traverser = make_traverser({'context': baz, 'view_name': 'bar'}) self._registerTraverser(traverser) self.assertRaises(KeyError, self._callFUT, resource, 'baz') self.assertEqual(resource.request.environ['PATH_INFO'], 'baz') @@ -603,7 +627,7 @@ class FindResourceTests(unittest.TestCase): def test_relative_tuple_notfound(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':'bar'}) + traverser = make_traverser({'context': baz, 'view_name': 'bar'}) self._registerTraverser(traverser) self.assertRaises(KeyError, self._callFUT, resource, ('baz',)) self.assertEqual(resource.request.environ['PATH_INFO'], 'baz') @@ -613,7 +637,7 @@ class FindResourceTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':''}) + traverser = make_traverser({'context': root, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, '/') self.assertEqual(result, root) @@ -625,7 +649,7 @@ class FindResourceTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':''}) + traverser = make_traverser({'context': root, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(resource, ('',)) self.assertEqual(result, root) @@ -637,7 +661,7 @@ class FindResourceTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':'fuz'}) + traverser = make_traverser({'context': root, 'view_name': 'fuz'}) self._registerTraverser(traverser) self.assertRaises(KeyError, self._callFUT, resource, '/') self.assertEqual(root.wascontext, True) @@ -648,7 +672,7 @@ class FindResourceTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':'fuz'}) + traverser = make_traverser({'context': root, 'view_name': 'fuz'}) self._registerTraverser(traverser) self.assertRaises(KeyError, self._callFUT, resource, ('',)) self.assertEqual(root.wascontext, True) @@ -669,24 +693,27 @@ class FindResourceTests(unittest.TestCase): # solution: encode string to ascii in pyramid.traversal.traverse # before passing it along to webob as path_info from pyramid.traversal import ResourceTreeTraverser + unprintable = DummyContext() root = DummyContext(unprintable) unprintable.__parent__ = root unprintable.__name__ = text_( - b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') + b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8' + ) root.__parent__ = None root.__name__ = None traverser = ResourceTreeTraverser self._registerTraverser(traverser) result = self._callFUT( - root, - text_(b'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') - ) + root, text_(b'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') + ) self.assertEqual(result, unprintable) + class ResourcePathTests(unittest.TestCase): def _callFUT(self, resource, *elements): from pyramid.traversal import resource_path + return resource_path(resource, *elements) def test_it(self): @@ -724,7 +751,7 @@ class ResourcePathTests(unittest.TestCase): root.__parent__ = None root.__name__ = 'flubadub' result = self._callFUT(root) - self.assertEqual(result, 'flubadub') # insane case + self.assertEqual(result, 'flubadub') # insane case def test_root_object_nonnull_name_indirect(self): root = DummyContext() @@ -734,7 +761,7 @@ class ResourcePathTests(unittest.TestCase): other.__parent__ = root other.__name__ = 'barker' result = self._callFUT(other) - self.assertEqual(result, 'flubadub/barker') # insane case + self.assertEqual(result, 'flubadub/barker') # insane case def test_nonroot_default(self): root = DummyContext() @@ -759,9 +786,11 @@ class ResourcePathTests(unittest.TestCase): result = self._callFUT(other2) self.assertEqual(result, '//other2') + class ResourcePathTupleTests(unittest.TestCase): def _callFUT(self, resource, *elements): from pyramid.traversal import resource_path_tuple + return resource_path_tuple(resource, *elements) def test_it(self): @@ -778,8 +807,9 @@ class ResourcePathTupleTests(unittest.TestCase): baz.__parent__ = bar baz.__name__ = 'baz' result = self._callFUT(baz, 'this/theotherthing', 'that') - self.assertEqual(result, ('','foo ', 'bar', 'baz', 'this/theotherthing', - 'that')) + self.assertEqual( + result, ('', 'foo ', 'bar', 'baz', 'this/theotherthing', 'that') + ) def test_root_default(self): root = DummyContext() @@ -796,7 +826,7 @@ class ResourcePathTupleTests(unittest.TestCase): other.__parent__ = root other.__name__ = 'other' result = self._callFUT(other) - self.assertEqual(result, ('', 'other',)) + self.assertEqual(result, ('', 'other')) def test_nonroot_default(self): root = DummyContext() @@ -821,9 +851,11 @@ class ResourcePathTupleTests(unittest.TestCase): result = self._callFUT(other2) self.assertEqual(result, ('', '', 'other2')) + class QuotePathSegmentTests(unittest.TestCase): def _callFUT(self, s): from pyramid.traversal import quote_path_segment + return quote_path_segment(s) def test_unicode(self): @@ -840,10 +872,11 @@ class QuotePathSegmentTests(unittest.TestCase): s = 12345 result = self._callFUT(s) self.assertEqual(result, '12345') - + def test_long(self): from pyramid.compat import long import sys + s = long(sys.maxsize + 1) result = self._callFUT(s) expected = str(s) @@ -853,27 +886,32 @@ class QuotePathSegmentTests(unittest.TestCase): class Foo(object): def __str__(self): return 'abc' + s = Foo() result = self._callFUT(s) self.assertEqual(result, 'abc') + class ResourceURLTests(unittest.TestCase): def _makeOne(self, context, url): return self._getTargetClass()(context, url) def _getTargetClass(self): from pyramid.traversal import ResourceURL + return ResourceURL def test_instance_conforms_to_IResourceURL(self): from pyramid.interfaces import IResourceURL from zope.interface.verify import verifyObject + context = DummyContext() request = DummyRequest() verifyObject(IResourceURL, self._makeOne(context, request)) def test_IResourceURL_attributes_with_vroot(self): from pyramid.interfaces import VH_ROOT_KEY + root = DummyContext() root.__parent__ = None root.__name__ = None @@ -883,16 +921,19 @@ class ResourceURLTests(unittest.TestCase): two = DummyContext() two.__parent__ = one two.__name__ = 'two' - environ = {VH_ROOT_KEY:'/one'} + environ = {VH_ROOT_KEY: '/one'} request = DummyRequest(environ) context_url = self._makeOne(two, request) self.assertEqual(context_url.physical_path, '/one/two/') self.assertEqual(context_url.virtual_path, '/two/') - self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two','')) + self.assertEqual( + context_url.physical_path_tuple, ('', 'one', 'two', '') + ) self.assertEqual(context_url.virtual_path_tuple, ('', 'two', '')) - + def test_IResourceURL_attributes_vroot_ends_with_slash(self): from pyramid.interfaces import VH_ROOT_KEY + root = DummyContext() root.__parent__ = None root.__name__ = None @@ -902,14 +943,16 @@ class ResourceURLTests(unittest.TestCase): two = DummyContext() two.__parent__ = one two.__name__ = 'two' - environ = {VH_ROOT_KEY:'/one/'} + environ = {VH_ROOT_KEY: '/one/'} request = DummyRequest(environ) context_url = self._makeOne(two, request) self.assertEqual(context_url.physical_path, '/one/two/') self.assertEqual(context_url.virtual_path, '/two/') - self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two','')) + self.assertEqual( + context_url.physical_path_tuple, ('', 'one', 'two', '') + ) self.assertEqual(context_url.virtual_path_tuple, ('', 'two', '')) - + def test_IResourceURL_attributes_no_vroot(self): root = DummyContext() root.__parent__ = None @@ -925,8 +968,13 @@ class ResourceURLTests(unittest.TestCase): context_url = self._makeOne(two, request) self.assertEqual(context_url.physical_path, '/one/two/') self.assertEqual(context_url.virtual_path, '/one/two/') - self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two','')) - self.assertEqual(context_url.virtual_path_tuple, ('', 'one', 'two', '')) + self.assertEqual( + context_url.physical_path_tuple, ('', 'one', 'two', '') + ) + self.assertEqual( + context_url.virtual_path_tuple, ('', 'one', 'two', '') + ) + class TestVirtualRoot(unittest.TestCase): def setUp(self): @@ -937,13 +985,16 @@ class TestVirtualRoot(unittest.TestCase): def _callFUT(self, resource, request): from pyramid.traversal import virtual_root + return virtual_root(resource, request) def _registerTraverser(self, traverser): from pyramid.threadlocal import get_current_registry + reg = get_current_registry() from pyramid.interfaces import ITraverser from zope.interface import Interface + reg.registerAdapter(traverser, (Interface,), ITraverser) def test_virtual_root_no_virtual_root_path(self): @@ -967,15 +1018,16 @@ class TestVirtualRoot(unittest.TestCase): def test_virtual_root_with_virtual_root_path(self): from pyramid.interfaces import VH_ROOT_KEY + root = DummyContext() root.__parent__ = None context = DummyContext() context.__name__ = 'one' context.__parent__ = root traversed_to = DummyContext() - environ = {VH_ROOT_KEY:'/one'} + environ = {VH_ROOT_KEY: '/one'} request = DummyRequest(environ) - traverser = make_traverser({'context':traversed_to, 'view_name':''}) + traverser = make_traverser({'context': traversed_to, 'view_name': ''}) self._registerTraverser(traverser) result = self._callFUT(context, request) self.assertEqual(result, traversed_to) @@ -996,6 +1048,7 @@ class TestVirtualRoot(unittest.TestCase): result = self._callFUT(context, request) self.assertEqual(result, context) + class TraverseTests(unittest.TestCase): def setUp(self): cleanUp() @@ -1005,56 +1058,62 @@ class TraverseTests(unittest.TestCase): def _callFUT(self, context, name): from pyramid.traversal import traverse + return traverse(context, name) def _registerTraverser(self, traverser): from pyramid.threadlocal import get_current_registry + reg = get_current_registry() from pyramid.interfaces import ITraverser from zope.interface import Interface + reg.registerAdapter(traverser, (Interface,), ITraverser) def test_request_has_registry(self): from pyramid.threadlocal import get_current_registry + resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ['']) self.assertEqual(resource.request.registry, get_current_registry()) def test_list(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ['']) self.assertEqual(resource.request.environ['PATH_INFO'], '/') def test_generator(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) + def foo(): yield '' + self._callFUT(resource, foo()) self.assertEqual(resource.request.environ['PATH_INFO'], '/') def test_self_string_found(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, '') self.assertEqual(resource.request.environ['PATH_INFO'], '') def test_self_unicode_found(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, text_('')) self.assertEqual(resource.request.environ['PATH_INFO'], '') def test_self_tuple_found(self): resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ()) self.assertEqual(resource.request.environ['PATH_INFO'], '') @@ -1062,7 +1121,7 @@ class TraverseTests(unittest.TestCase): def test_relative_string_found(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':''}) + traverser = make_traverser({'context': baz, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, 'baz') self.assertEqual(resource.request.environ['PATH_INFO'], 'baz') @@ -1070,7 +1129,7 @@ class TraverseTests(unittest.TestCase): def test_relative_tuple_found(self): resource = DummyContext() baz = DummyContext() - traverser = make_traverser({'context':baz, 'view_name':''}) + traverser = make_traverser({'context': baz, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ('baz',)) self.assertEqual(resource.request.environ['PATH_INFO'], 'baz') @@ -1080,7 +1139,7 @@ class TraverseTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':''}) + traverser = make_traverser({'context': root, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, '/') self.assertEqual(root.wascontext, True) @@ -1091,7 +1150,7 @@ class TraverseTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':''}) + traverser = make_traverser({'context': root, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ('',)) self.assertEqual(root.wascontext, True) @@ -1102,7 +1161,7 @@ class TraverseTests(unittest.TestCase): resource = DummyContext() resource.__parent__ = root resource.__name__ = 'baz' - traverser = make_traverser({'context':root, 'view_name':''}) + traverser = make_traverser({'context': root, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, []) self.assertEqual(resource.wascontext, True) @@ -1118,19 +1177,24 @@ class TraverseTests(unittest.TestCase): from pyramid.interfaces import IRequestFactory from pyramid.request import Request from pyramid.threadlocal import get_current_registry + reg = get_current_registry() + class MyRequest(Request): pass + reg.registerUtility(MyRequest, IRequestFactory) resource = DummyContext() - traverser = make_traverser({'context':resource, 'view_name':''}) + traverser = make_traverser({'context': resource, 'view_name': ''}) self._registerTraverser(traverser) self._callFUT(resource, ['']) self.assertEqual(resource.request.__class__, MyRequest) + class TestDefaultRootFactory(unittest.TestCase): def _getTargetClass(self): from pyramid.traversal import DefaultRootFactory + return DefaultRootFactory def _makeOne(self, environ): @@ -1139,13 +1203,16 @@ class TestDefaultRootFactory(unittest.TestCase): def test_it(self): class DummyRequest(object): pass + root = self._makeOne(DummyRequest()) self.assertEqual(root.__parent__, None) self.assertEqual(root.__name__, None) + class Test__join_path_tuple(unittest.TestCase): def _callFUT(self, tup): from pyramid.traversal import _join_path_tuple + return _join_path_tuple(tup) def test_empty_tuple(self): @@ -1158,12 +1225,25 @@ class Test__join_path_tuple(unittest.TestCase): self.assertEqual(result, 'x') def test_segments_with_unsafes(self): - safe_segments = tuple(u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=:@") + safe_segments = tuple( + u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=:@" + ) result = self._callFUT(safe_segments) self.assertEqual(result, u'/'.join(safe_segments)) - unsafe_segments = tuple(chr(i) for i in range(0x20, 0x80) if not chr(i) in safe_segments) + (u'あ',) + unsafe_segments = tuple( + chr(i) for i in range(0x20, 0x80) if not chr(i) in safe_segments + ) + (u'あ',) result = self._callFUT(unsafe_segments) - self.assertEqual(result, u'/'.join(''.join('%%%02X' % (ord(c) if isinstance(c, str) else c) for c in unsafe_segment.encode('utf-8')) for unsafe_segment in unsafe_segments)) + self.assertEqual( + result, + u'/'.join( + ''.join( + '%%%02X' % (ord(c) if isinstance(c, str) else c) + for c in unsafe_segment.encode('utf-8') + ) + for unsafe_segment in unsafe_segments + ), + ) def make_traverser(result): @@ -1171,13 +1251,17 @@ def make_traverser(result): def __init__(self, context): self.context = context context.wascontext = True + def __call__(self, request): self.context.request = request return result + return DummyTraverser + class DummyContext(object): __parent__ = None + def __init__(self, next=None, name=None): self.next = next self.__name__ = name @@ -1188,11 +1272,17 @@ class DummyContext(object): return self.next def __repr__(self): - return '<DummyContext with name %s at id %s>'%(self.__name__, id(self)) + return '<DummyContext with name %s at id %s>' % ( + self.__name__, + id(self), + ) + class DummyRequest: - application_url = 'http://example.com:5432' # app_url never ends with slash + application_url = ( + 'http://example.com:5432' + ) # app_url never ends with slash matchdict = None matched_route = None @@ -1212,10 +1302,11 @@ class DummyRequest: self._path_info = v path_info = property(_get_path_info, _set_path_info) - + def _makeRequest(environ=None): from pyramid.registry import Registry + request = DummyRequest() request.registry = Registry() return request diff --git a/tests/test_tweens.py b/tests/test_tweens.py index 2e74ad7cf..ab9b8b0cd 100644 --- a/tests/test_tweens.py +++ b/tests/test_tweens.py @@ -1,6 +1,7 @@ import unittest from pyramid import testing + class Test_excview_tween_factory(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -10,14 +11,17 @@ class Test_excview_tween_factory(unittest.TestCase): def _makeOne(self, handler, registry=None): from pyramid.tweens import excview_tween_factory + if registry is None: registry = self.config.registry return excview_tween_factory(handler, registry) def test_it_passthrough_no_exception(self): dummy_response = DummyResponse() + def handler(request): return dummy_response + tween = self._makeOne(handler) request = DummyRequest() result = tween(request) @@ -28,9 +32,12 @@ class Test_excview_tween_factory(unittest.TestCase): def test_it_catches_notfound(self): from pyramid.request import Request from pyramid.httpexceptions import HTTPNotFound + self.config.add_notfound_view(lambda exc, request: exc) + def handler(request): raise HTTPNotFound + tween = self._makeOne(handler) request = Request.blank('/') request.registry = self.config.registry @@ -42,11 +49,15 @@ class Test_excview_tween_factory(unittest.TestCase): def test_it_catches_with_predicate(self): from pyramid.request import Request from pyramid.response import Response + def excview(request): return Response('foo') + self.config.add_view(excview, context=ValueError, request_method='GET') + def handler(request): raise ValueError + tween = self._makeOne(handler) request = Request.blank('/') request.registry = self.config.registry @@ -57,10 +68,15 @@ class Test_excview_tween_factory(unittest.TestCase): def test_it_reraises_on_mismatch(self): from pyramid.request import Request - def excview(request): pass + + def excview(request): + pass + self.config.add_view(excview, context=ValueError, request_method='GET') + def handler(request): raise ValueError + tween = self._makeOne(handler) request = Request.blank('/') request.registry = self.config.registry @@ -71,8 +87,10 @@ class Test_excview_tween_factory(unittest.TestCase): def test_it_reraises_on_no_match(self): from pyramid.request import Request + def handler(request): raise ValueError + tween = self._makeOne(handler) request = Request.blank('/') request.registry = self.config.registry @@ -80,9 +98,11 @@ class Test_excview_tween_factory(unittest.TestCase): self.assertIsNone(request.exception) self.assertIsNone(request.exc_info) + class DummyRequest: exception = None exc_info = None + class DummyResponse: pass diff --git a/tests/test_url.py b/tests/test_url.py index 3d161da21..3acfbc876 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -4,10 +4,8 @@ import warnings from pyramid import testing -from pyramid.compat import ( - text_, - WIN, - ) +from pyramid.compat import text_, WIN + class TestURLMethodsMixin(unittest.TestCase): def setUp(self): @@ -15,16 +13,20 @@ class TestURLMethodsMixin(unittest.TestCase): def tearDown(self): testing.tearDown() - + def _makeOne(self, environ=None): from pyramid.url import URLMethodsMixin + if environ is None: environ = {} + class Request(URLMethodsMixin): application_url = 'http://example.com:5432' script_name = '' + def __init__(self, environ): self.environ = environ + request = Request(environ) request.registry = self.config.registry return request @@ -32,12 +34,17 @@ class TestURLMethodsMixin(unittest.TestCase): def _registerResourceURL(self, reg): from pyramid.interfaces import IResourceURL from zope.interface import Interface + class DummyResourceURL(object): physical_path = '/context/' virtual_path = '/context/' - def __init__(self, context, request): pass - reg.registerAdapter(DummyResourceURL, (Interface, Interface), - IResourceURL) + + def __init__(self, context, request): + pass + + reg.registerAdapter( + DummyResourceURL, (Interface, Interface), IResourceURL + ) return DummyResourceURL def test_resource_url_root_default(self): @@ -53,8 +60,8 @@ class TestURLMethodsMixin(unittest.TestCase): context = DummyContext() result = request.resource_url(context, 'this/theotherthing', 'that') self.assertEqual( - result, - 'http://example.com:5432/context/this%2Ftheotherthing/that') + result, 'http://example.com:5432/context/this%2Ftheotherthing/that' + ) def test_resource_url_unicode_in_element_names(self): request = self._makeOne() @@ -62,16 +69,16 @@ class TestURLMethodsMixin(unittest.TestCase): uc = text_(b'La Pe\xc3\xb1a', 'utf-8') context = DummyContext() result = request.resource_url(context, uc) - self.assertEqual(result, - 'http://example.com:5432/context/La%20Pe%C3%B1a') + self.assertEqual( + result, 'http://example.com:5432/context/La%20Pe%C3%B1a' + ) def test_resource_url_at_sign_in_element_names(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, '@@myview') - self.assertEqual(result, - 'http://example.com:5432/context/@@myview') + self.assertEqual(result, 'http://example.com:5432/context/@@myview') def test_resource_url_element_names_url_quoted(self): request = self._makeOne() @@ -85,68 +92,69 @@ class TestURLMethodsMixin(unittest.TestCase): self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, 'a', query='(openlayers)') - self.assertEqual(result, - 'http://example.com:5432/context/a?(openlayers)') + self.assertEqual( + result, 'http://example.com:5432/context/a?(openlayers)' + ) def test_resource_url_with_query_dict(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() uc = text_(b'La Pe\xc3\xb1a', 'utf-8') - result = request.resource_url(context, 'a', query={'a':uc}) - self.assertEqual(result, - 'http://example.com:5432/context/a?a=La+Pe%C3%B1a') + result = request.resource_url(context, 'a', query={'a': uc}) + self.assertEqual( + result, 'http://example.com:5432/context/a?a=La+Pe%C3%B1a' + ) def test_resource_url_with_query_seq(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() uc = text_(b'La Pe\xc3\xb1a', 'utf-8') - result = request.resource_url(context, 'a', query=[('a', 'hi there'), - ('b', uc)]) - self.assertEqual(result, - 'http://example.com:5432/context/a?a=hi+there&b=La+Pe%C3%B1a') + result = request.resource_url( + context, 'a', query=[('a', 'hi there'), ('b', uc)] + ) + self.assertEqual( + result, + 'http://example.com:5432/context/a?a=hi+there&b=La+Pe%C3%B1a', + ) def test_resource_url_with_query_empty(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, 'a', query=[]) - self.assertEqual(result, - 'http://example.com:5432/context/a') + self.assertEqual(result, 'http://example.com:5432/context/a') def test_resource_url_with_query_None(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, 'a', query=None) - self.assertEqual(result, - 'http://example.com:5432/context/a') + self.assertEqual(result, 'http://example.com:5432/context/a') def test_resource_url_anchor_is_after_root_when_no_elements(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, anchor='a') - self.assertEqual(result, - 'http://example.com:5432/context/#a') + self.assertEqual(result, 'http://example.com:5432/context/#a') def test_resource_url_anchor_is_after_elements_when_no_qs(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, 'a', anchor='b') - self.assertEqual(result, - 'http://example.com:5432/context/a#b') + self.assertEqual(result, 'http://example.com:5432/context/a#b') def test_resource_url_anchor_is_after_qs_when_qs_is_present(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() - result = request.resource_url(context, 'a', - query={'b':'c'}, anchor='d') - self.assertEqual(result, - 'http://example.com:5432/context/a?b=c#d') + result = request.resource_url( + context, 'a', query={'b': 'c'}, anchor='d' + ) + self.assertEqual(result, 'http://example.com:5432/context/a?b=c#d') def test_resource_url_anchor_is_encoded_utf8_if_unicode(self): request = self._makeOne() @@ -154,16 +162,16 @@ class TestURLMethodsMixin(unittest.TestCase): context = DummyContext() uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, anchor=uc) - self.assertEqual(result, - 'http://example.com:5432/context/#La%20Pe%C3%B1a') + self.assertEqual( + result, 'http://example.com:5432/context/#La%20Pe%C3%B1a' + ) def test_resource_url_anchor_is_urlencoded_safe(self): request = self._makeOne() self._registerResourceURL(request.registry) context = DummyContext() result = request.resource_url(context, anchor=' /#?&+') - self.assertEqual(result, - 'http://example.com:5432/context/#%20/%23?&+') + self.assertEqual(result, 'http://example.com:5432/context/#%20/%23?&+') def test_resource_url_anchor_is_None(self): request = self._makeOne() @@ -189,7 +197,7 @@ class TestURLMethodsMixin(unittest.TestCase): root = DummyContext() result = request.resource_url(root) self.assertEqual(result, 'http://example.com:5432/context/') - + def test_resource_url_with_app_url(self): request = self._makeOne() self._registerResourceURL(request.registry) @@ -199,10 +207,10 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_scheme(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) self._registerResourceURL(request.registry) root = DummyContext() @@ -211,10 +219,10 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_host(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) self._registerResourceURL(request.registry) root = DummyContext() @@ -223,10 +231,10 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_port(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) self._registerResourceURL(request.registry) root = DummyContext() @@ -235,30 +243,33 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_local_url(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) self._registerResourceURL(request.registry) root = DummyContext() + def resource_url(req, info): self.assertEqual(req, request) self.assertEqual(info['virtual_path'], '/context/') self.assertEqual(info['physical_path'], '/context/') self.assertEqual(info['app_url'], 'http://example.com:5432') return 'http://example.com/contextabc/' + root.__resource_url__ = resource_url result = request.resource_url(root) self.assertEqual(result, 'http://example.com/contextabc/') def test_resource_url_with_route_name_no_remainder_on_adapter(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # no virtual_path_tuple on adapter @@ -273,11 +284,12 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_route_name_remainder_on_adapter(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -292,11 +304,12 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_with_route_name_and_app_url(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -305,17 +318,20 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route) request.registry.registerUtility(mapper, IRoutesMapper) root = DummyContext() - result = request.resource_url(root, route_name='foo', app_url='app_url') + result = request.resource_url( + root, route_name='foo', app_url='app_url' + ) self.assertEqual(result, 'app_url/1/2/3') self.assertEqual(route.kw, {'traverse': ('', 'a', 'b', 'c', '')}) def test_resource_url_with_route_name_and_scheme_host_port_etc(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -324,19 +340,26 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route) request.registry.registerUtility(mapper, IRoutesMapper) root = DummyContext() - result = request.resource_url(root, route_name='foo', scheme='scheme', - host='host', port='port', query={'a':'1'}, - anchor='anchor') + result = request.resource_url( + root, + route_name='foo', + scheme='scheme', + host='host', + port='port', + query={'a': '1'}, + anchor='anchor', + ) self.assertEqual(result, 'scheme://host:port/1/2/3?a=1#anchor') self.assertEqual(route.kw, {'traverse': ('', 'a', 'b', 'c', '')}) def test_resource_url_with_route_name_and_route_kwargs(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -346,22 +369,21 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) root = DummyContext() result = request.resource_url( - root, route_name='foo', route_kw={'a':'1', 'b':'2'}) + root, route_name='foo', route_kw={'a': '1', 'b': '2'} + ) self.assertEqual(result, 'http://example.com:5432/1/2/3') self.assertEqual( - route.kw, - {'traverse': ('', 'a', 'b', 'c', ''), - 'a':'1', - 'b':'2'} - ) + route.kw, {'traverse': ('', 'a', 'b', 'c', ''), 'a': '1', 'b': '2'} + ) def test_resource_url_with_route_name_and_elements(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -371,16 +393,17 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) root = DummyContext() result = request.resource_url(root, 'e1', 'e2', route_name='foo') - self.assertEqual(result, 'http://example.com:5432/1/2/3/e1/e2') + self.assertEqual(result, 'http://example.com:5432/1/2/3/e1/e2') self.assertEqual(route.kw, {'traverse': ('', 'a', 'b', 'c', '')}) - + def test_resource_url_with_route_name_and_remainder_name(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'8080', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '8080', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) adapter = self._registerResourceURL(request.registry) # virtual_path_tuple on adapter @@ -389,11 +412,12 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route) request.registry.registerUtility(mapper, IRoutesMapper) root = DummyContext() - result = request.resource_url(root, route_name='foo', - route_remainder_name='fred') + result = request.resource_url( + root, route_name='foo', route_remainder_name='fred' + ) self.assertEqual(result, 'http://example.com:5432/1/2/3') self.assertEqual(route.kw, {'fred': ('', 'a', 'b', 'c', '')}) - + def test_resource_path(self): request = self._makeOne() self._registerResourceURL(request.registry) @@ -407,37 +431,39 @@ class TestURLMethodsMixin(unittest.TestCase): root = DummyContext() result = request.resource_path(root, anchor='abc') self.assertEqual(result, '/context/#abc') - + def test_route_url_with_elements(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', 'extra1', 'extra2') - self.assertEqual(result, - 'http://example.com:5432/1/2/3/extra1/extra2') + self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2') def test_route_url_with_elements_path_endswith_slash(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3/')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', 'extra1', 'extra2') - self.assertEqual(result, - 'http://example.com:5432/1/2/3/extra1/extra2') + self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2') def test_route_url_no_elements(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - result = request.route_url('flub', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_(b"foo")) - self.assertEqual(result, - 'http://example.com:5432/1/2/3?a=1#foo') + result = request.route_url( + 'flub', a=1, b=2, c=3, _query={'a': 1}, _anchor=text_(b"foo") + ) + self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1#foo') def test_route_url_with_query_None(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) @@ -446,27 +472,32 @@ class TestURLMethodsMixin(unittest.TestCase): def test_route_url_with_anchor_binary(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _anchor=b"La Pe\xc3\xb1a") - self.assertEqual(result, - 'http://example.com:5432/1/2/3#La%20Pe%C3%B1a') + self.assertEqual( + result, 'http://example.com:5432/1/2/3#La%20Pe%C3%B1a' + ) def test_route_url_with_anchor_unicode(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) anchor = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.route_url('flub', _anchor=anchor) - self.assertEqual(result, - 'http://example.com:5432/1/2/3#La%20Pe%C3%B1a') + self.assertEqual( + result, 'http://example.com:5432/1/2/3#La%20Pe%C3%B1a' + ) def test_route_url_with_anchor_None(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) @@ -476,83 +507,81 @@ class TestURLMethodsMixin(unittest.TestCase): def test_route_url_with_query(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - result = request.route_url('flub', _query={'q':'1'}) - self.assertEqual(result, - 'http://example.com:5432/1/2/3?q=1') + result = request.route_url('flub', _query={'q': '1'}) + self.assertEqual(result, 'http://example.com:5432/1/2/3?q=1') def test_route_url_with_query_str(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _query='(openlayers)') - self.assertEqual(result, - 'http://example.com:5432/1/2/3?(openlayers)') + self.assertEqual(result, 'http://example.com:5432/1/2/3?(openlayers)') def test_route_url_with_empty_query(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _query={}) - self.assertEqual(result, - 'http://example.com:5432/1/2/3') + self.assertEqual(result, 'http://example.com:5432/1/2/3') def test_route_url_with_app_url(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _app_url='http://example2.com') - self.assertEqual(result, - 'http://example2.com/1/2/3') + self.assertEqual(result, 'http://example2.com/1/2/3') def test_route_url_with_host(self): from pyramid.interfaces import IRoutesMapper - environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'5432', - } + + environ = {'wsgi.url_scheme': 'http', 'SERVER_PORT': '5432'} request = self._makeOne(environ) mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _host='someotherhost.com') - self.assertEqual(result, - 'http://someotherhost.com:5432/1/2/3') + self.assertEqual(result, 'http://someotherhost.com:5432/1/2/3') def test_route_url_with_port(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'5432', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '5432', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _port='8080') - self.assertEqual(result, - 'http://example.com:8080/1/2/3') + self.assertEqual(result, 'http://example.com:8080/1/2/3') def test_route_url_with_scheme(self): from pyramid.interfaces import IRoutesMapper + environ = { - 'wsgi.url_scheme':'http', - 'SERVER_PORT':'5432', - 'SERVER_NAME':'example.com', - } + 'wsgi.url_scheme': 'http', + 'SERVER_PORT': '5432', + 'SERVER_NAME': 'example.com', + } request = self._makeOne(environ) mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _scheme='https') - self.assertEqual(result, - 'https://example.com/1/2/3') - + self.assertEqual(result, 'https://example.com/1/2/3') + def test_route_url_generation_error(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(raise_exc=KeyError) request.registry.registerUtility(mapper, IRoutesMapper) @@ -561,50 +590,59 @@ class TestURLMethodsMixin(unittest.TestCase): def test_route_url_generate_doesnt_receive_query_or_anchor(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() route = DummyRoute(result='') mapper = DummyRoutesMapper(route=route) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', _query=dict(name='some_name')) - self.assertEqual(route.kw, {}) # shouldnt have anchor/query + self.assertEqual(route.kw, {}) # shouldnt have anchor/query self.assertEqual(result, 'http://example.com:5432?name=some_name') def test_route_url_with_pregenerator(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() route = DummyRoute(result='/1/2/3') + def pregenerator(request, elements, kw): - return ('a',), {'_app_url':'http://example2.com'} + return ('a',), {'_app_url': 'http://example2.com'} + route.pregenerator = pregenerator mapper = DummyRoutesMapper(route=route) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub') - self.assertEqual(result, 'http://example2.com/1/2/3/a') - self.assertEqual(route.kw, {}) # shouldnt have anchor/query + self.assertEqual(result, 'http://example2.com/1/2/3/a') + self.assertEqual(route.kw, {}) # shouldnt have anchor/query def test_route_url_with_anchor_app_url_elements_and_query(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute(result='/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - result = request.route_url('flub', 'element1', - _app_url='http://example2.com', - _anchor='anchor', _query={'q':'1'}) - self.assertEqual(result, - 'http://example2.com/1/2/3/element1?q=1#anchor') + result = request.route_url( + 'flub', + 'element1', + _app_url='http://example2.com', + _anchor='anchor', + _query={'q': '1'}, + ) + self.assertEqual( + result, 'http://example2.com/1/2/3/element1?q=1#anchor' + ) def test_route_url_integration_with_real_request(self): # to try to replicate https://github.com/Pylons/pyramid/issues/213 from pyramid.interfaces import IRoutesMapper from pyramid.request import Request + request = Request.blank('/') request.registry = self.config.registry mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', 'extra1', 'extra2') - self.assertEqual(result, - 'http://localhost/1/2/3/extra1/extra2') - + self.assertEqual(result, 'http://localhost/1/2/3/extra1/extra2') def test_current_route_url_current_request_has_no_route(self): request = self._makeOne() @@ -612,34 +650,44 @@ class TestURLMethodsMixin(unittest.TestCase): def test_current_route_url_with_elements_query_and_anchor(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() route = DummyRoute('/1/2/3') mapper = DummyRoutesMapper(route=route) request.matched_route = route request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) - result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_(b"foo")) - self.assertEqual(result, - 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') + result = request.current_route_url( + 'extra1', 'extra2', _query={'a': 1}, _anchor=text_(b"foo") + ) + self.assertEqual( + result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo' + ) def test_current_route_url_with_route_name(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() route = DummyRoute('/1/2/3') mapper = DummyRoutesMapper(route=route) request.matched_route = route request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) - result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_(b"foo"), - _route_name='bar') - self.assertEqual(result, - 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') + result = request.current_route_url( + 'extra1', + 'extra2', + _query={'a': 1}, + _anchor=text_(b"foo"), + _route_name='bar', + ) + self.assertEqual( + result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo' + ) def test_current_route_url_with_request_query(self): from pyramid.interfaces import IRoutesMapper from webob.multidict import GetDict + request = self._makeOne() request.GET = GetDict([('q', '123')], {}) route = DummyRoute('/1/2/3') @@ -648,27 +696,30 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url() - self.assertEqual(result, - 'http://example.com:5432/1/2/3?q=123') + self.assertEqual(result, 'http://example.com:5432/1/2/3?q=123') def test_current_route_url_with_request_query_duplicate_entries(self): from pyramid.interfaces import IRoutesMapper from webob.multidict import GetDict + request = self._makeOne() request.GET = GetDict( - [('q', '123'), ('b', '2'), ('b', '2'), ('q', '456')], {}) + [('q', '123'), ('b', '2'), ('b', '2'), ('q', '456')], {} + ) route = DummyRoute('/1/2/3') mapper = DummyRoutesMapper(route=route) request.matched_route = route request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url() - self.assertEqual(result, - 'http://example.com:5432/1/2/3?q=123&b=2&b=2&q=456') + self.assertEqual( + result, 'http://example.com:5432/1/2/3?q=123&b=2&b=2&q=456' + ) def test_current_route_url_with_query_override(self): from pyramid.interfaces import IRoutesMapper from webob.multidict import GetDict + request = self._makeOne() request.GET = GetDict([('q', '123')], {}) route = DummyRoute('/1/2/3') @@ -676,12 +727,12 @@ class TestURLMethodsMixin(unittest.TestCase): request.matched_route = route request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) - result = request.current_route_url(_query={'a':1}) - self.assertEqual(result, - 'http://example.com:5432/1/2/3?a=1') + result = request.current_route_url(_query={'a': 1}) + self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1') def test_current_route_path(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() route = DummyRoute('/1/2/3') mapper = DummyRoutesMapper(route=route) @@ -689,38 +740,56 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.script_name = '/script_name' request.registry.registerUtility(mapper, IRoutesMapper) - result = request.current_route_path('extra1', 'extra2', _query={'a':1}, - _anchor=text_(b"foo")) + result = request.current_route_path( + 'extra1', 'extra2', _query={'a': 1}, _anchor=text_(b"foo") + ) self.assertEqual(result, '/script_name/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_elements(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) request.script_name = '' - result = request.route_path('flub', 'extra1', 'extra2', - a=1, b=2, c=3, _query={'a':1}, - _anchor=text_(b"foo")) + result = request.route_path( + 'flub', + 'extra1', + 'extra2', + a=1, + b=2, + c=3, + _query={'a': 1}, + _anchor=text_(b"foo"), + ) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_script_name(self): from pyramid.interfaces import IRoutesMapper + request = self._makeOne() request.script_name = '/foo' mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - result = request.route_path('flub', 'extra1', 'extra2', - a=1, b=2, c=3, _query={'a':1}, - _anchor=text_(b"foo")) + result = request.route_path( + 'flub', + 'extra1', + 'extra2', + a=1, + b=2, + c=3, + _query={'a': 1}, + _anchor=text_(b"foo"), + ) self.assertEqual(result, '/foo/1/2/3/extra1/extra2?a=1#foo') - + def test_static_url_staticurlinfo_notfound(self): request = self._makeOne() self.assertRaises(ValueError, request.static_url, 'static/foo.css') def test_static_url_abspath(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() info = DummyStaticURLInfo('abc') registry = request.registry @@ -728,31 +797,34 @@ class TestURLMethodsMixin(unittest.TestCase): abspath = makeabs('static', 'foo.css') result = request.static_url(abspath) self.assertEqual(result, 'abc') - self.assertEqual(info.args, (makeabs('static', 'foo.css'), request, {})) + self.assertEqual( + info.args, (makeabs('static', 'foo.css'), request, {}) + ) request = self._makeOne() def test_static_url_found_rel(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() info = DummyStaticURLInfo('abc') request.registry.registerUtility(info, IStaticURLInfo) result = request.static_url('static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, {}) ) + self.assertEqual(info.args, ('tests:static/foo.css', request, {})) def test_static_url_abs(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() info = DummyStaticURLInfo('abc') request.registry.registerUtility(info, IStaticURLInfo) result = request.static_url('tests:static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, {}) ) + self.assertEqual(info.args, ('tests:static/foo.css', request, {})) def test_static_url_found_abs_no_registry_on_request(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() registry = request.registry info = DummyStaticURLInfo('abc') @@ -760,12 +832,12 @@ class TestURLMethodsMixin(unittest.TestCase): del request.registry result = request.static_url('tests:static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, {}) ) + self.assertEqual(info.args, ('tests:static/foo.css', request, {})) def test_static_url_abspath_integration_with_staticurlinfo(self): from pyramid.interfaces import IStaticURLInfo from pyramid.config.views import StaticURLInfo + info = StaticURLInfo() here = os.path.abspath(os.path.dirname(__file__)) info.add(self.config, 'absstatic', here) @@ -774,12 +846,14 @@ class TestURLMethodsMixin(unittest.TestCase): registry.registerUtility(info, IStaticURLInfo) abspath = os.path.join(here, 'test_url.py') result = request.static_url(abspath) - self.assertEqual(result, - 'http://example.com:5432/absstatic/test_url.py') + self.assertEqual( + result, 'http://example.com:5432/absstatic/test_url.py' + ) def test_static_url_noscheme_uses_scheme_from_request(self): from pyramid.interfaces import IStaticURLInfo from pyramid.config.views import StaticURLInfo + info = StaticURLInfo() here = os.path.abspath(os.path.dirname(__file__)) info.add(self.config, '//subdomain.example.com/static', here) @@ -788,11 +862,13 @@ class TestURLMethodsMixin(unittest.TestCase): registry.registerUtility(info, IStaticURLInfo) abspath = os.path.join(here, 'test_url.py') result = request.static_url(abspath) - self.assertEqual(result, - 'https://subdomain.example.com/static/test_url.py') + self.assertEqual( + result, 'https://subdomain.example.com/static/test_url.py' + ) def test_static_path_abspath(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() request.script_name = '/foo' info = DummyStaticURLInfo('abc') @@ -801,214 +877,208 @@ class TestURLMethodsMixin(unittest.TestCase): abspath = makeabs('static', 'foo.css') result = request.static_path(abspath) self.assertEqual(result, 'abc') - self.assertEqual(info.args, (makeabs('static', 'foo.css'), request, - {'_app_url':'/foo'}) - ) + self.assertEqual( + info.args, + (makeabs('static', 'foo.css'), request, {'_app_url': '/foo'}), + ) def test_static_path_found_rel(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() request.script_name = '/foo' info = DummyStaticURLInfo('abc') request.registry.registerUtility(info, IStaticURLInfo) result = request.static_path('static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, - {'_app_url':'/foo'}) - ) + self.assertEqual( + info.args, ('tests:static/foo.css', request, {'_app_url': '/foo'}) + ) def test_static_path_abs(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() request.script_name = '/foo' info = DummyStaticURLInfo('abc') request.registry.registerUtility(info, IStaticURLInfo) result = request.static_path('tests:static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, - {'_app_url':'/foo'}) - ) + self.assertEqual( + info.args, ('tests:static/foo.css', request, {'_app_url': '/foo'}) + ) def test_static_path(self): from pyramid.interfaces import IStaticURLInfo + request = self._makeOne() request.script_name = '/foo' info = DummyStaticURLInfo('abc') request.registry.registerUtility(info, IStaticURLInfo) result = request.static_path('static/foo.css') self.assertEqual(result, 'abc') - self.assertEqual(info.args, - ('tests:static/foo.css', request, - {'_app_url':'/foo'}) - ) + self.assertEqual( + info.args, ('tests:static/foo.css', request, {'_app_url': '/foo'}) + ) def test_partial_application_url_with_http_host_default_port_http(self): - environ = { - 'wsgi.url_scheme':'http', - 'HTTP_HOST':'example.com:80', - } + environ = {'wsgi.url_scheme': 'http', 'HTTP_HOST': 'example.com:80'} request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'http://example.com') def test_partial_application_url_with_http_host_default_port_https(self): - environ = { - 'wsgi.url_scheme':'https', - 'HTTP_HOST':'example.com:443', - } + environ = {'wsgi.url_scheme': 'https', 'HTTP_HOST': 'example.com:443'} request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'https://example.com') def test_partial_application_url_with_http_host_nondefault_port_http(self): - environ = { - 'wsgi.url_scheme':'http', - 'HTTP_HOST':'example.com:8080', - } + environ = {'wsgi.url_scheme': 'http', 'HTTP_HOST': 'example.com:8080'} request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'http://example.com:8080') - def test_partial_application_url_with_http_host_nondefault_port_https(self): - environ = { - 'wsgi.url_scheme':'https', - 'HTTP_HOST':'example.com:4443', - } + def test_partial_application_url_with_http_host_nondefault_port_https( + self + ): + environ = {'wsgi.url_scheme': 'https', 'HTTP_HOST': 'example.com:4443'} request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'https://example.com:4443') def test_partial_application_url_with_http_host_no_colon(self): environ = { - 'wsgi.url_scheme':'http', - 'HTTP_HOST':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'HTTP_HOST': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'http://example.com') def test_partial_application_url_no_http_host(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url() self.assertEqual(result, 'http://example.com') - + def test_partial_application_replace_port(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url(port=8080) self.assertEqual(result, 'http://example.com:8080') def test_partial_application_replace_scheme_https_special_case(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url(scheme='https') self.assertEqual(result, 'https://example.com') def test_partial_application_replace_scheme_https_special_case_avoid(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url(scheme='https', port='8080') self.assertEqual(result, 'https://example.com:8080') def test_partial_application_replace_scheme_http_special_case(self): environ = { - 'wsgi.url_scheme':'https', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'8080', - } + 'wsgi.url_scheme': 'https', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '8080', + } request = self._makeOne(environ) result = request._partial_application_url(scheme='http') self.assertEqual(result, 'http://example.com') def test_partial_application_replace_scheme_http_special_case_avoid(self): environ = { - 'wsgi.url_scheme':'https', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'8000', - } + 'wsgi.url_scheme': 'https', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '8000', + } request = self._makeOne(environ) result = request._partial_application_url(scheme='http', port='8080') self.assertEqual(result, 'http://example.com:8080') - + def test_partial_application_replace_host_no_port(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url(host='someotherhost.com') self.assertEqual(result, 'http://someotherhost.com') def test_partial_application_replace_host_with_port(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'8000', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '8000', + } request = self._makeOne(environ) - result = request._partial_application_url(host='someotherhost.com:8080') + result = request._partial_application_url( + host='someotherhost.com:8080' + ) self.assertEqual(result, 'http://someotherhost.com:8080') def test_partial_application_replace_host_and_port(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) - result = request._partial_application_url(host='someotherhost.com:8080', - port='8000') + result = request._partial_application_url( + host='someotherhost.com:8080', port='8000' + ) self.assertEqual(result, 'http://someotherhost.com:8000') def test_partial_application_replace_host_port_and_scheme(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'80', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '80', + } request = self._makeOne(environ) result = request._partial_application_url( - host='someotherhost.com:8080', - port='8000', - scheme='https', - ) + host='someotherhost.com:8080', port='8000', scheme='https' + ) self.assertEqual(result, 'https://someotherhost.com:8000') - + def test_partial_application_url_with_custom_script_name(self): environ = { - 'wsgi.url_scheme':'http', - 'SERVER_NAME':'example.com', - 'SERVER_PORT':'8000', - } + 'wsgi.url_scheme': 'http', + 'SERVER_NAME': 'example.com', + 'SERVER_PORT': '8000', + } request = self._makeOne(environ) request.script_name = '/abc' result = request._partial_application_url() - self.assertEqual(result, 'http://example.com:8000/abc') - + self.assertEqual(result, 'http://example.com:8000/abc') + + class Test_route_url(unittest.TestCase): def _callFUT(self, route_name, request, *elements, **kw): from pyramid.url import route_url + return route_url(route_name, request, *elements, **kw) def _makeRequest(self): @@ -1018,6 +1088,7 @@ class Test_route_url(unittest.TestCase): self.elements = elements self.kw = kw return 'route url' + return Request() def test_it(self): @@ -1026,11 +1097,13 @@ class Test_route_url(unittest.TestCase): self.assertEqual(result, 'route url') self.assertEqual(request.route_name, 'abc') self.assertEqual(request.elements, ('a',)) - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_route_path(unittest.TestCase): def _callFUT(self, route_name, request, *elements, **kw): from pyramid.url import route_path + return route_path(route_name, request, *elements, **kw) def _makeRequest(self): @@ -1040,6 +1113,7 @@ class Test_route_path(unittest.TestCase): self.elements = elements self.kw = kw return 'route path' + return Request() def test_it(self): @@ -1048,11 +1122,13 @@ class Test_route_path(unittest.TestCase): self.assertEqual(result, 'route path') self.assertEqual(request.route_name, 'abc') self.assertEqual(request.elements, ('a',)) - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_resource_url(unittest.TestCase): def _callFUT(self, resource, request, *elements, **kw): from pyramid.url import resource_url + return resource_url(resource, request, *elements, **kw) def _makeRequest(self): @@ -1062,6 +1138,7 @@ class Test_resource_url(unittest.TestCase): self.elements = elements self.kw = kw return 'resource url' + return Request() def test_it(self): @@ -1070,11 +1147,13 @@ class Test_resource_url(unittest.TestCase): self.assertEqual(result, 'resource url') self.assertEqual(request.resource, 'abc') self.assertEqual(request.elements, ('a',)) - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_static_url(unittest.TestCase): def _callFUT(self, path, request, **kw): from pyramid.url import static_url + return static_url(path, request, **kw) def _makeRequest(self): @@ -1083,6 +1162,7 @@ class Test_static_url(unittest.TestCase): self.path = path self.kw = kw return 'static url' + return Request() def test_it_abs(self): @@ -1090,25 +1170,27 @@ class Test_static_url(unittest.TestCase): result = self._callFUT('/foo/bar/abc', request, _app_url='') self.assertEqual(result, 'static url') self.assertEqual(request.path, '/foo/bar/abc') - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) def test_it_absspec(self): request = self._makeRequest() result = self._callFUT('foo:abc', request, _anchor='anchor') self.assertEqual(result, 'static url') self.assertEqual(request.path, 'foo:abc') - self.assertEqual(request.kw, {'_anchor':'anchor'}) + self.assertEqual(request.kw, {'_anchor': 'anchor'}) def test_it_rel(self): request = self._makeRequest() result = self._callFUT('abc', request, _app_url='') self.assertEqual(result, 'static url') self.assertEqual(request.path, 'tests:abc') - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_static_path(unittest.TestCase): def _callFUT(self, path, request, **kw): from pyramid.url import static_path + return static_path(path, request, **kw) def _makeRequest(self): @@ -1117,6 +1199,7 @@ class Test_static_path(unittest.TestCase): self.path = path self.kw = kw return 'static path' + return Request() def test_it_abs(self): @@ -1124,25 +1207,27 @@ class Test_static_path(unittest.TestCase): result = self._callFUT('/foo/bar/abc', request, _anchor='anchor') self.assertEqual(result, 'static path') self.assertEqual(request.path, '/foo/bar/abc') - self.assertEqual(request.kw, {'_anchor':'anchor'}) + self.assertEqual(request.kw, {'_anchor': 'anchor'}) def test_it_absspec(self): request = self._makeRequest() result = self._callFUT('foo:abc', request, _anchor='anchor') self.assertEqual(result, 'static path') self.assertEqual(request.path, 'foo:abc') - self.assertEqual(request.kw, {'_anchor':'anchor'}) + self.assertEqual(request.kw, {'_anchor': 'anchor'}) def test_it_rel(self): request = self._makeRequest() result = self._callFUT('abc', request, _app_url='') self.assertEqual(result, 'static path') self.assertEqual(request.path, 'tests:abc') - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_current_route_url(unittest.TestCase): def _callFUT(self, request, *elements, **kw): from pyramid.url import current_route_url + return current_route_url(request, *elements, **kw) def _makeRequest(self): @@ -1151,6 +1236,7 @@ class Test_current_route_url(unittest.TestCase): self.elements = elements self.kw = kw return 'current route url' + return Request() def test_it(self): @@ -1158,11 +1244,13 @@ class Test_current_route_url(unittest.TestCase): result = self._callFUT(request, 'abc', _app_url='') self.assertEqual(result, 'current route url') self.assertEqual(request.elements, ('abc',)) - self.assertEqual(request.kw, {'_app_url':''}) + self.assertEqual(request.kw, {'_app_url': ''}) + class Test_current_route_path(unittest.TestCase): def _callFUT(self, request, *elements, **kw): from pyramid.url import current_route_path + return current_route_path(request, *elements, **kw) def _makeRequest(self): @@ -1171,6 +1259,7 @@ class Test_current_route_path(unittest.TestCase): self.elements = elements self.kw = kw return 'current route path' + return Request() def test_it(self): @@ -1178,10 +1267,10 @@ class Test_current_route_path(unittest.TestCase): result = self._callFUT(request, 'abc', _anchor='abc') self.assertEqual(result, 'current route path') self.assertEqual(request.elements, ('abc',)) - self.assertEqual(request.kw, {'_anchor':'abc'}) + self.assertEqual(request.kw, {'_anchor': 'abc'}) -class Test_external_static_url_integration(unittest.TestCase): +class Test_external_static_url_integration(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -1190,6 +1279,7 @@ class Test_external_static_url_integration(unittest.TestCase): def _makeRequest(self): from pyramid.request import Request + return Request.blank('/') def test_generate_external_url(self): @@ -1197,16 +1287,16 @@ class Test_external_static_url_integration(unittest.TestCase): request = self._makeRequest() request.registry = self.config.registry self.assertEqual( - request.route_url('acme', foo='bar'), - 'https://acme.org/path/bar') + request.route_url('acme', foo='bar'), 'https://acme.org/path/bar' + ) def test_generate_external_url_without_scheme(self): self.config.add_route('acme', '//acme.org/path/{foo}') request = self._makeRequest() request.registry = self.config.registry self.assertEqual( - request.route_url('acme', foo='bar'), - 'http://acme.org/path/bar') + request.route_url('acme', foo='bar'), 'http://acme.org/path/bar' + ) def test_generate_external_url_with_explicit_scheme(self): self.config.add_route('acme', '//acme.org/path/{foo}') @@ -1214,14 +1304,20 @@ class Test_external_static_url_integration(unittest.TestCase): request.registry = self.config.registry self.assertEqual( request.route_url('acme', foo='bar', _scheme='https'), - 'https://acme.org/path/bar') + 'https://acme.org/path/bar', + ) def test_generate_external_url_with_explicit_app_url(self): self.config.add_route('acme', 'http://acme.org/path/{foo}') request = self._makeRequest() request.registry = self.config.registry - self.assertRaises(ValueError, - request.route_url, 'acme', foo='bar', _app_url='http://fakeme.com') + self.assertRaises( + ValueError, + request.route_url, + 'acme', + foo='bar', + _app_url='http://fakeme.com', + ) def test_generate_external_url_route_path(self): self.config.add_route('acme', 'https://acme.org/path/{foo}') @@ -1233,26 +1329,30 @@ class Test_external_static_url_integration(unittest.TestCase): def pregenerator(request, elements, kw): kw['_query'] = {'q': 'foo'} return elements, kw - self.config.add_route('acme', 'https://acme.org/path/{foo}', - pregenerator=pregenerator) + + self.config.add_route( + 'acme', 'https://acme.org/path/{foo}', pregenerator=pregenerator + ) request = self._makeRequest() request.registry = self.config.registry self.assertEqual( request.route_url('acme', foo='bar'), - 'https://acme.org/path/bar?q=foo') + 'https://acme.org/path/bar?q=foo', + ) def test_external_url_with_route_prefix(self): def includeme(config): config.add_route('acme', '//acme.org/{foo}') + self.config.include(includeme, route_prefix='some_prefix') request = self._makeRequest() request.registry = self.config.registry self.assertEqual( - request.route_url('acme', foo='bar'), - 'http://acme.org/bar') + request.route_url('acme', foo='bar'), 'http://acme.org/bar' + ) -class Test_with_route_prefix(unittest.TestCase): +class Test_with_route_prefix(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -1261,6 +1361,7 @@ class Test_with_route_prefix(unittest.TestCase): def _makeRequest(self, route): from pyramid.request import Request + return Request.blank(route) def test_old_route_is_preserved(self): @@ -1288,10 +1389,7 @@ class Test_with_route_prefix(unittest.TestCase): with self.config.route_prefix_context('bar'): self.config.add_route('acme', '/foo') request = self._makeRequest('/') - self.assertEqual( - request.route_url('acme'), - 'http://localhost/bar/foo', - ) + self.assertEqual(request.route_url('acme'), 'http://localhost/bar/foo') def test_route_does_not_have_prefix(self): with self.config.route_prefix_context('bar'): @@ -1299,10 +1397,7 @@ class Test_with_route_prefix(unittest.TestCase): self.config.add_route('acme', '/foo') request = self._makeRequest('/') - self.assertEqual( - request.route_url('acme'), - 'http://localhost/foo', - ) + self.assertEqual(request.route_url('acme'), 'http://localhost/foo') def test_error_reset_prefix(self): self.config.route_prefix = 'old_prefix' @@ -1315,28 +1410,34 @@ class Test_with_route_prefix(unittest.TestCase): assert self.config.route_prefix == 'old_prefix' + class DummyContext(object): def __init__(self, next=None): self.next = next - + + class DummyRoutesMapper: raise_exc = None + def __init__(self, route=None, raise_exc=False): self.route = route def get_route(self, route_name): return self.route + class DummyRoute: pregenerator = None name = 'route' + def __init__(self, result='/1/2/3'): self.result = result def generate(self, kw): self.kw = kw return self.result - + + class DummyStaticURLInfo: def __init__(self, result): self.result = result @@ -1344,9 +1445,10 @@ class DummyStaticURLInfo: def generate(self, path, request, **kw): self.args = path, request, kw return self.result - + + def makeabs(*elements): - if WIN: # pragma: no cover + if WIN: # pragma: no cover return r'c:\\' + os.path.sep.join(elements) else: return os.path.sep + os.path.sep.join(elements) diff --git a/tests/test_urldispatch.py b/tests/test_urldispatch.py index 06f4ad793..e90fbfa0b 100644 --- a/tests/test_urldispatch.py +++ b/tests/test_urldispatch.py @@ -1,13 +1,12 @@ import unittest from pyramid import testing -from pyramid.compat import ( - text_, - PY2, - ) +from pyramid.compat import text_, PY2 + class TestRoute(unittest.TestCase): def _getTargetClass(self): from pyramid.urldispatch import Route + return Route def _makeOne(self, *arg): @@ -16,10 +15,12 @@ class TestRoute(unittest.TestCase): def test_provides_IRoute(self): from pyramid.interfaces import IRoute from zope.interface.verify import verifyObject + verifyObject(IRoute, self._makeOne('name', 'pattern')) def test_ctor(self): import types + route = self._makeOne('name', ':path', 'factory') self.assertEqual(route.pattern, ':path') self.assertEqual(route.path, ':path') @@ -30,6 +31,7 @@ class TestRoute(unittest.TestCase): def test_ctor_defaults(self): import types + route = self._makeOne('name', ':path') self.assertEqual(route.pattern, ':path') self.assertEqual(route.path, ':path') @@ -40,11 +42,12 @@ class TestRoute(unittest.TestCase): def test_match(self): route = self._makeOne('name', ':path') - self.assertEqual(route.match('/whatever'), {'path':'whatever'}) + self.assertEqual(route.match('/whatever'), {'path': 'whatever'}) def test_generate(self): route = self._makeOne('name', ':path') - self.assertEqual(route.generate({'path':'abc'}), '/abc') + self.assertEqual(route.generate({'path': 'abc'}), '/abc') + class RoutesMapperTests(unittest.TestCase): def setUp(self): @@ -52,11 +55,11 @@ class RoutesMapperTests(unittest.TestCase): def tearDown(self): testing.tearDown() - + def _getRequest(self, **kw): from pyramid.threadlocal import get_current_registry - environ = {'SERVER_NAME':'localhost', - 'wsgi.url_scheme':'http'} + + environ = {'SERVER_NAME': 'localhost', 'wsgi.url_scheme': 'http'} environ.update(kw) request = DummyRequest(environ) reg = get_current_registry() @@ -65,6 +68,7 @@ class RoutesMapperTests(unittest.TestCase): def _getTargetClass(self): from pyramid.urldispatch import RoutesMapper + return RoutesMapper def _makeOne(self): @@ -74,6 +78,7 @@ class RoutesMapperTests(unittest.TestCase): def test_provides_IRoutesMapper(self): from pyramid.interfaces import IRoutesMapper from zope.interface.verify import verifyObject + verifyObject(IRoutesMapper, self._makeOne()) def test_no_route_matches(self): @@ -89,36 +94,43 @@ class RoutesMapperTests(unittest.TestCase): mapper.connect('foo', 'archives/:action/:article2') self.assertEqual(len(mapper.routelist), 1) self.assertEqual(len(mapper.routes), 1) - self.assertEqual(mapper.routes['foo'].pattern, - 'archives/:action/:article2') - self.assertEqual(mapper.routelist[0].pattern, - 'archives/:action/:article2') + self.assertEqual( + mapper.routes['foo'].pattern, 'archives/:action/:article2' + ) + self.assertEqual( + mapper.routelist[0].pattern, 'archives/:action/:article2' + ) def test_connect_static(self): mapper = self._makeOne() mapper.connect('foo', 'archives/:action/:article', static=True) self.assertEqual(len(mapper.routelist), 0) self.assertEqual(len(mapper.routes), 1) - self.assertEqual(mapper.routes['foo'].pattern, - 'archives/:action/:article') + self.assertEqual( + mapper.routes['foo'].pattern, 'archives/:action/:article' + ) def test_connect_static_overridden(self): mapper = self._makeOne() mapper.connect('foo', 'archives/:action/:article', static=True) self.assertEqual(len(mapper.routelist), 0) self.assertEqual(len(mapper.routes), 1) - self.assertEqual(mapper.routes['foo'].pattern, - 'archives/:action/:article') + self.assertEqual( + mapper.routes['foo'].pattern, 'archives/:action/:article' + ) mapper.connect('foo', 'archives/:action/:article2') self.assertEqual(len(mapper.routelist), 1) self.assertEqual(len(mapper.routes), 1) - self.assertEqual(mapper.routes['foo'].pattern, - 'archives/:action/:article2') - self.assertEqual(mapper.routelist[0].pattern, - 'archives/:action/:article2') + self.assertEqual( + mapper.routes['foo'].pattern, 'archives/:action/:article2' + ) + self.assertEqual( + mapper.routelist[0].pattern, 'archives/:action/:article2' + ) def test___call__pathinfo_cant_be_decoded(self): from pyramid.exceptions import URLDecodeError + mapper = self._makeOne() if PY2: path_info = b'\xff\xfe\xe6\x00' @@ -138,8 +150,9 @@ class RoutesMapperTests(unittest.TestCase): def test___call__route_matches_with_predicates(self): mapper = self._makeOne() - mapper.connect('foo', 'archives/:action/:article', - predicates=[lambda *arg: True]) + mapper.connect( + 'foo', 'archives/:action/:article', predicates=[lambda *arg: True] + ) request = self._getRequest(PATH_INFO='/archives/action1/article1') result = mapper(request) self.assertEqual(result['route'], mapper.routes['foo']) @@ -148,8 +161,11 @@ class RoutesMapperTests(unittest.TestCase): def test___call__route_fails_to_match_with_predicates(self): mapper = self._makeOne() - mapper.connect('foo', 'archives/:action/article1', - predicates=[lambda *arg: True, lambda *arg: False]) + mapper.connect( + 'foo', + 'archives/:action/article1', + predicates=[lambda *arg: True, lambda *arg: False], + ) mapper.connect('bar', 'archives/:action/:article') request = self._getRequest(PATH_INFO='/archives/action1/article1') result = mapper(request) @@ -159,10 +175,12 @@ class RoutesMapperTests(unittest.TestCase): def test___call__custom_predicate_gets_info(self): mapper = self._makeOne() + def pred(info, request): - self.assertEqual(info['match'], {'action':'action1'}) + self.assertEqual(info['match'], {'action': 'action1'}) self.assertEqual(info['route'], mapper.routes['foo']) return True + mapper.connect('foo', 'archives/:action/article1', predicates=[pred]) request = self._getRequest(PATH_INFO='/archives/action1/article1') mapper(request) @@ -172,8 +190,9 @@ class RoutesMapperTests(unittest.TestCase): # http://labs.creativecommons.org/2010/01/13/cc-engine-and-web-non-frameworks/ mapper = self._makeOne() mapper.connect('rdf', 'licenses/:license_code/:license_version/rdf') - mapper.connect('juri', - 'licenses/:license_code/:license_version/:jurisdiction') + mapper.connect( + 'juri', 'licenses/:license_code/:license_version/:jurisdiction' + ) request = self._getRequest(PATH_INFO='/licenses/1/v2/rdf') result = mapper(request) @@ -236,6 +255,7 @@ class RoutesMapperTests(unittest.TestCase): def test_get_routes(self): from pyramid.urldispatch import Route + mapper = self._makeOne() self.assertEqual(mapper.get_routes(), []) mapper.connect('whatever', 'archives/:action/:article') @@ -256,131 +276,167 @@ class RoutesMapperTests(unittest.TestCase): def test_generate(self): mapper = self._makeOne() + def generator(kw): return 123 + route = DummyRoute(generator) - mapper.routes['abc'] = route + mapper.routes['abc'] = route self.assertEqual(mapper.generate('abc', {}), 123) + class TestCompileRoute(unittest.TestCase): def _callFUT(self, pattern): from pyramid.urldispatch import _compile_route + return _compile_route(pattern) def test_no_star(self): matcher, generator = self._callFUT('/foo/:baz/biz/:buz/bar') - self.assertEqual(matcher('/foo/baz/biz/buz/bar'), - {'baz':'baz', 'buz':'buz'}) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar'), {'baz': 'baz', 'buz': 'buz'} + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar') + self.assertEqual(generator({'baz': 1, 'buz': 2}), '/foo/1/biz/2/bar') def test_with_star(self): matcher, generator = self._callFUT('/foo/:baz/biz/:buz/bar*traverse') - self.assertEqual(matcher('/foo/baz/biz/buz/bar'), - {'baz':'baz', 'buz':'buz', 'traverse':()}) - self.assertEqual(matcher('/foo/baz/biz/buz/bar/everything/else/here'), - {'baz':'baz', 'buz':'buz', - 'traverse':('everything', 'else', 'here')}) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar'), + {'baz': 'baz', 'buz': 'buz', 'traverse': ()}, + ) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar/everything/else/here'), + { + 'baz': 'baz', + 'buz': 'buz', + 'traverse': ('everything', 'else', 'here'), + }, + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator( - {'baz':1, 'buz':2, 'traverse':'/a/b'}), '/foo/1/biz/2/bar/a/b') - + self.assertEqual( + generator({'baz': 1, 'buz': 2, 'traverse': '/a/b'}), + '/foo/1/biz/2/bar/a/b', + ) + def test_with_bracket_star(self): matcher, generator = self._callFUT( - '/foo/{baz}/biz/{buz}/bar{remainder:.*}') - self.assertEqual(matcher('/foo/baz/biz/buz/bar'), - {'baz':'baz', 'buz':'buz', 'remainder':''}) - self.assertEqual(matcher('/foo/baz/biz/buz/bar/everything/else/here'), - {'baz':'baz', 'buz':'buz', - 'remainder':'/everything/else/here'}) + '/foo/{baz}/biz/{buz}/bar{remainder:.*}' + ) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar'), + {'baz': 'baz', 'buz': 'buz', 'remainder': ''}, + ) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar/everything/else/here'), + {'baz': 'baz', 'buz': 'buz', 'remainder': '/everything/else/here'}, + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator( - {'baz':1, 'buz':2, 'remainder':'/a/b'}), '/foo/1/biz/2/bar/a/b') + self.assertEqual( + generator({'baz': 1, 'buz': 2, 'remainder': '/a/b'}), + '/foo/1/biz/2/bar/a/b', + ) def test_no_beginning_slash(self): matcher, generator = self._callFUT('foo/:baz/biz/:buz/bar') - self.assertEqual(matcher('/foo/baz/biz/buz/bar'), - {'baz':'baz', 'buz':'buz'}) + self.assertEqual( + matcher('/foo/baz/biz/buz/bar'), {'baz': 'baz', 'buz': 'buz'} + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar') + self.assertEqual(generator({'baz': 1, 'buz': 2}), '/foo/1/biz/2/bar') def test_custom_regex(self): matcher, generator = self._callFUT('foo/{baz}/biz/{buz:[^/\.]+}.{bar}') - self.assertEqual(matcher('/foo/baz/biz/buz.bar'), - {'baz':'baz', 'buz':'buz', 'bar':'bar'}) + self.assertEqual( + matcher('/foo/baz/biz/buz.bar'), + {'baz': 'baz', 'buz': 'buz', 'bar': 'bar'}, + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), - '/foo/1/biz/2.html') - + self.assertEqual( + generator({'baz': 1, 'buz': 2, 'bar': 'html'}), '/foo/1/biz/2.html' + ) + def test_custom_regex_with_colons(self): - matcher, generator = self._callFUT('foo/{baz}/biz/{buz:(?:[^/\.]+)}.{bar}') - self.assertEqual(matcher('/foo/baz/biz/buz.bar'), - {'baz':'baz', 'buz':'buz', 'bar':'bar'}) + matcher, generator = self._callFUT( + 'foo/{baz}/biz/{buz:(?:[^/\.]+)}.{bar}' + ) + self.assertEqual( + matcher('/foo/baz/biz/buz.bar'), + {'baz': 'baz', 'buz': 'buz', 'bar': 'bar'}, + ) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), - '/foo/1/biz/2.html') + self.assertEqual( + generator({'baz': 1, 'buz': 2, 'bar': 'html'}), '/foo/1/biz/2.html' + ) def test_mixed_newstyle_oldstyle_pattern_defaults_to_newstyle(self): # pattern: '\\/foo\\/(?P<baz>abc)\\/biz\\/(?P<buz>[^/]+)\\/bar$' # note presence of :abc in pattern (oldstyle match) matcher, generator = self._callFUT('foo/{baz:abc}/biz/{buz}/bar') - self.assertEqual(matcher('/foo/abc/biz/buz/bar'), - {'baz':'abc', 'buz':'buz'}) - self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar') + self.assertEqual( + matcher('/foo/abc/biz/buz/bar'), {'baz': 'abc', 'buz': 'buz'} + ) + self.assertEqual(generator({'baz': 1, 'buz': 2}), '/foo/1/biz/2/bar') def test_custom_regex_with_embedded_squigglies(self): matcher, generator = self._callFUT('/{buz:\d{4}}') - self.assertEqual(matcher('/2001'), {'buz':'2001'}) + self.assertEqual(matcher('/2001'), {'buz': '2001'}) self.assertEqual(matcher('/200'), None) - self.assertEqual(generator({'buz':2001}), '/2001') + self.assertEqual(generator({'buz': 2001}), '/2001') def test_custom_regex_with_embedded_squigglies2(self): matcher, generator = self._callFUT('/{buz:\d{3,4}}') - self.assertEqual(matcher('/2001'), {'buz':'2001'}) - self.assertEqual(matcher('/200'), {'buz':'200'}) + self.assertEqual(matcher('/2001'), {'buz': '2001'}) + self.assertEqual(matcher('/200'), {'buz': '200'}) self.assertEqual(matcher('/20'), None) - self.assertEqual(generator({'buz':2001}), '/2001') + self.assertEqual(generator({'buz': 2001}), '/2001') def test_custom_regex_with_embedded_squigglies3(self): matcher, generator = self._callFUT( - '/{buz:(\d{2}|\d{4})-[a-zA-Z]{3,4}-\d{2}}') - self.assertEqual(matcher('/2001-Nov-15'), {'buz':'2001-Nov-15'}) - self.assertEqual(matcher('/99-June-10'), {'buz':'99-June-10'}) + '/{buz:(\d{2}|\d{4})-[a-zA-Z]{3,4}-\d{2}}' + ) + self.assertEqual(matcher('/2001-Nov-15'), {'buz': '2001-Nov-15'}) + self.assertEqual(matcher('/99-June-10'), {'buz': '99-June-10'}) self.assertEqual(matcher('/2-Nov-15'), None) self.assertEqual(matcher('/200-Nov-15'), None) self.assertEqual(matcher('/2001-No-15'), None) - self.assertEqual(generator({'buz':'2001-Nov-15'}), '/2001-Nov-15') - self.assertEqual(generator({'buz':'99-June-10'}), '/99-June-10') + self.assertEqual(generator({'buz': '2001-Nov-15'}), '/2001-Nov-15') + self.assertEqual(generator({'buz': '99-June-10'}), '/99-June-10') def test_pattern_with_high_order_literal(self): pattern = text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8') matcher, generator = self._callFUT(pattern) - self.assertEqual(matcher(text_(b'/La Pe\xc3\xb1a/x', 'utf-8')), - {'x':'x'}) - self.assertEqual(generator({'x':'1'}), '/La%20Pe%C3%B1a/1') + self.assertEqual( + matcher(text_(b'/La Pe\xc3\xb1a/x', 'utf-8')), {'x': 'x'} + ) + self.assertEqual(generator({'x': '1'}), '/La%20Pe%C3%B1a/1') def test_pattern_generate_with_high_order_dynamic(self): pattern = '/{x}' _, generator = self._callFUT(pattern) self.assertEqual( - generator({'x':text_(b'La Pe\xc3\xb1a', 'utf-8')}), - '/La%20Pe%C3%B1a') + generator({'x': text_(b'La Pe\xc3\xb1a', 'utf-8')}), + '/La%20Pe%C3%B1a', + ) def test_docs_sample_generate(self): # sample from urldispatch.rst pattern = text_(b'/La Pe\xc3\xb1a/{city}', 'utf-8') _, generator = self._callFUT(pattern) self.assertEqual( - generator({'city':text_(b'Qu\xc3\xa9bec', 'utf-8')}), - '/La%20Pe%C3%B1a/Qu%C3%A9bec') + generator({'city': text_(b'Qu\xc3\xa9bec', 'utf-8')}), + '/La%20Pe%C3%B1a/Qu%C3%A9bec', + ) def test_generate_with_mixedtype_values(self): pattern = '/{city}/{state}' _, generator = self._callFUT(pattern) result = generator( - {'city': text_(b'Qu\xc3\xa9bec', 'utf-8'), - 'state': b'La Pe\xc3\xb1a'} - ) + { + 'city': text_(b'Qu\xc3\xa9bec', 'utf-8'), + 'state': b'La Pe\xc3\xb1a', + } + ) self.assertEqual(result, '/Qu%C3%A9bec/La%20Pe%C3%B1a') # should be a native string self.assertEqual(type(result), str) @@ -394,7 +450,7 @@ class TestCompileRoute(unittest.TestCase): _, generator = self._callFUT(pattern) result = generator( {'remainder': text_(b'/Qu\xc3\xa9bec/La Pe\xc3\xb1a', 'utf-8')} - ) + ) self.assertEqual(result, '/abc/Qu%C3%A9bec/La%20Pe%C3%B1a') # should be a native string self.assertEqual(type(result), str) @@ -402,22 +458,23 @@ class TestCompileRoute(unittest.TestCase): def test_generate_with_string_remainder_and_nonstring_replacement(self): pattern = text_(b'/abc/*remainder', 'utf-8') _, generator = self._callFUT(pattern) - result = generator( - {'remainder': None} - ) + result = generator({'remainder': None}) self.assertEqual(result, '/abc/None') # should be a native string self.assertEqual(type(result), str) + class TestCompileRouteFunctional(unittest.TestCase): def matches(self, pattern, path, expected): from pyramid.urldispatch import _compile_route + matcher = _compile_route(pattern)[0] result = matcher(path) self.assertEqual(result, expected) def generates(self, pattern, dict, result): from pyramid.urldispatch import _compile_route + self.assertEqual(_compile_route(pattern)[1](dict), result) def test_matcher_functional_notdynamic(self): @@ -432,108 +489,165 @@ class TestCompileRouteFunctional(unittest.TestCase): self.matches('/{x}', '', None) self.matches('/{x}', '/', None) self.matches('/abc/{def}', '/abc/', None) - self.matches('/{x}', '/a', {'x':'a'}) - self.matches('zzz/{x}', '/zzz/abc', {'x':'abc'}) - self.matches('zzz/{x}*traverse', '/zzz/abc', {'x':'abc', 'traverse':()}) - self.matches('zzz/{x}*traverse', '/zzz/abc/def/g', - {'x':'abc', 'traverse':('def', 'g')}) - self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) - self.matches('*traverse', '/zzz/ abc', {'traverse':('zzz', ' abc')}) + self.matches('/{x}', '/a', {'x': 'a'}) + self.matches('zzz/{x}', '/zzz/abc', {'x': 'abc'}) + self.matches( + 'zzz/{x}*traverse', '/zzz/abc', {'x': 'abc', 'traverse': ()} + ) + self.matches( + 'zzz/{x}*traverse', + '/zzz/abc/def/g', + {'x': 'abc', 'traverse': ('def', 'g')}, + ) + self.matches('*traverse', '/zzz/abc', {'traverse': ('zzz', 'abc')}) + self.matches('*traverse', '/zzz/ abc', {'traverse': ('zzz', ' abc')}) #'/La%20Pe%C3%B1a' - self.matches('{x}', text_(b'/La Pe\xc3\xb1a', 'utf-8'), - {'x':text_(b'La Pe\xc3\xb1a', 'utf-8')}) + self.matches( + '{x}', + text_(b'/La Pe\xc3\xb1a', 'utf-8'), + {'x': text_(b'La Pe\xc3\xb1a', 'utf-8')}, + ) # '/La%20Pe%C3%B1a/x' - self.matches('*traverse', text_(b'/La Pe\xc3\xb1a/x'), - {'traverse':(text_(b'La Pe\xc3\xb1a'), 'x')}) - self.matches('/foo/{id}.html', '/foo/bar.html', {'id':'bar'}) - self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def', - {'num':'555', 'traverse':('abc', 'def')}) - self.matches('/{num:[0-9]*}/*traverse', '/555/abc/def', - {'num':'555', 'traverse':('abc', 'def')}) - self.matches('zzz/{_}', '/zzz/abc', {'_':'abc'}) - self.matches('zzz/{_abc}', '/zzz/abc', {'_abc':'abc'}) - self.matches('zzz/{abc_def}', '/zzz/abc', {'abc_def':'abc'}) + self.matches( + '*traverse', + text_(b'/La Pe\xc3\xb1a/x'), + {'traverse': (text_(b'La Pe\xc3\xb1a'), 'x')}, + ) + self.matches('/foo/{id}.html', '/foo/bar.html', {'id': 'bar'}) + self.matches( + '/{num:[0-9]+}/*traverse', + '/555/abc/def', + {'num': '555', 'traverse': ('abc', 'def')}, + ) + self.matches( + '/{num:[0-9]*}/*traverse', + '/555/abc/def', + {'num': '555', 'traverse': ('abc', 'def')}, + ) + self.matches('zzz/{_}', '/zzz/abc', {'_': 'abc'}) + self.matches('zzz/{_abc}', '/zzz/abc', {'_abc': 'abc'}) + self.matches('zzz/{abc_def}', '/zzz/abc', {'abc_def': 'abc'}) def test_matcher_functional_oldstyle(self): self.matches('/:x', '', None) self.matches('/:x', '/', None) self.matches('/abc/:def', '/abc/', None) - self.matches('/:x', '/a', {'x':'a'}) - self.matches('zzz/:x', '/zzz/abc', {'x':'abc'}) - self.matches('zzz/:x*traverse', '/zzz/abc', {'x':'abc', 'traverse':()}) - self.matches('zzz/:x*traverse', '/zzz/abc/def/g', - {'x':'abc', 'traverse':('def', 'g')}) - self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) - self.matches('*traverse', '/zzz/ abc', {'traverse':('zzz', ' abc')}) + self.matches('/:x', '/a', {'x': 'a'}) + self.matches('zzz/:x', '/zzz/abc', {'x': 'abc'}) + self.matches( + 'zzz/:x*traverse', '/zzz/abc', {'x': 'abc', 'traverse': ()} + ) + self.matches( + 'zzz/:x*traverse', + '/zzz/abc/def/g', + {'x': 'abc', 'traverse': ('def', 'g')}, + ) + self.matches('*traverse', '/zzz/abc', {'traverse': ('zzz', 'abc')}) + self.matches('*traverse', '/zzz/ abc', {'traverse': ('zzz', ' abc')}) #'/La%20Pe%C3%B1a' # pattern, path, expected - self.matches(':x', text_(b'/La Pe\xc3\xb1a', 'utf-8'), - {'x':text_(b'La Pe\xc3\xb1a', 'utf-8')}) + self.matches( + ':x', + text_(b'/La Pe\xc3\xb1a', 'utf-8'), + {'x': text_(b'La Pe\xc3\xb1a', 'utf-8')}, + ) # '/La%20Pe%C3%B1a/x' - self.matches('*traverse', text_(b'/La Pe\xc3\xb1a/x', 'utf-8'), - {'traverse':(text_(b'La Pe\xc3\xb1a', 'utf-8'), 'x')}) - self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'}) - self.matches('/foo/:id_html', '/foo/bar_html', {'id_html':'bar_html'}) - self.matches('zzz/:_', '/zzz/abc', {'_':'abc'}) - self.matches('zzz/:_abc', '/zzz/abc', {'_abc':'abc'}) - self.matches('zzz/:abc_def', '/zzz/abc', {'abc_def':'abc'}) + self.matches( + '*traverse', + text_(b'/La Pe\xc3\xb1a/x', 'utf-8'), + {'traverse': (text_(b'La Pe\xc3\xb1a', 'utf-8'), 'x')}, + ) + self.matches('/foo/:id.html', '/foo/bar.html', {'id': 'bar'}) + self.matches('/foo/:id_html', '/foo/bar_html', {'id_html': 'bar_html'}) + self.matches('zzz/:_', '/zzz/abc', {'_': 'abc'}) + self.matches('zzz/:_abc', '/zzz/abc', {'_abc': 'abc'}) + self.matches('zzz/:abc_def', '/zzz/abc', {'abc_def': 'abc'}) def test_generator_functional_notdynamic(self): self.generates('', {}, '/') self.generates('/', {}, '/') def test_generator_functional_newstyle(self): - self.generates('/{x}', {'x':''}, '/') - self.generates('/{x}', {'x':'a'}, '/a') - self.generates('/{x}', {'x':'a/b/c'}, '/a/b/c') - self.generates('/{x}', {'x':':@&+$,'}, '/:@&+$,') - self.generates('zzz/{x}', {'x':'abc'}, '/zzz/abc') - self.generates('zzz/{x}*traverse', {'x':'abc', 'traverse':''}, - '/zzz/abc') - self.generates('zzz/{x}*traverse', {'x':'abc', 'traverse':'/def/g'}, - '/zzz/abc/def/g') - self.generates('zzz/{x}*traverse', {'x':':@&+$,', 'traverse':'/:@&+$,'}, - '/zzz/:@&+$,/:@&+$,') - self.generates('/{x}', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, - '//La%20Pe%C3%B1a') - self.generates('/{x}*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), - 'y':'/rest/of/path'}, - '//La%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, - '/a/La%20Pe%C3%B1a') - self.generates('/foo/{id}.html', {'id':'bar'}, '/foo/bar.html') - self.generates('/foo/{_}', {'_':'20'}, '/foo/20') - self.generates('/foo/{_abc}', {'_abc':'20'}, '/foo/20') - self.generates('/foo/{abc_def}', {'abc_def':'20'}, '/foo/20') - + self.generates('/{x}', {'x': ''}, '/') + self.generates('/{x}', {'x': 'a'}, '/a') + self.generates('/{x}', {'x': 'a/b/c'}, '/a/b/c') + self.generates('/{x}', {'x': ':@&+$,'}, '/:@&+$,') + self.generates('zzz/{x}', {'x': 'abc'}, '/zzz/abc') + self.generates( + 'zzz/{x}*traverse', {'x': 'abc', 'traverse': ''}, '/zzz/abc' + ) + self.generates( + 'zzz/{x}*traverse', + {'x': 'abc', 'traverse': '/def/g'}, + '/zzz/abc/def/g', + ) + self.generates( + 'zzz/{x}*traverse', + {'x': ':@&+$,', 'traverse': '/:@&+$,'}, + '/zzz/:@&+$,/:@&+$,', + ) + self.generates( + '/{x}', + {'x': text_(b'/La Pe\xc3\xb1a', 'utf-8')}, + '//La%20Pe%C3%B1a', + ) + self.generates( + '/{x}*y', + {'x': text_(b'/La Pe\xc3\xb1a', 'utf-8'), 'y': '/rest/of/path'}, + '//La%20Pe%C3%B1a/rest/of/path', + ) + self.generates( + '*traverse', + {'traverse': ('a', text_(b'La Pe\xf1a'))}, + '/a/La%20Pe%C3%B1a', + ) + self.generates('/foo/{id}.html', {'id': 'bar'}, '/foo/bar.html') + self.generates('/foo/{_}', {'_': '20'}, '/foo/20') + self.generates('/foo/{_abc}', {'_abc': '20'}, '/foo/20') + self.generates('/foo/{abc_def}', {'abc_def': '20'}, '/foo/20') + def test_generator_functional_oldstyle(self): - self.generates('/:x', {'x':''}, '/') - self.generates('/:x', {'x':'a'}, '/a') - self.generates('zzz/:x', {'x':'abc'}, '/zzz/abc') - self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':''}, - '/zzz/abc') - self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':'/def/g'}, - '/zzz/abc/def/g') - self.generates('/:x', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, - '//La%20Pe%C3%B1a') - self.generates('/:x*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), - 'y':'/rest/of/path'}, - '//La%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, - '/a/La%20Pe%C3%B1a') - self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html') - self.generates('/foo/:_', {'_':'20'}, '/foo/20') - self.generates('/foo/:_abc', {'_abc':'20'}, '/foo/20') - self.generates('/foo/:abc_def', {'abc_def':'20'}, '/foo/20') + self.generates('/:x', {'x': ''}, '/') + self.generates('/:x', {'x': 'a'}, '/a') + self.generates('zzz/:x', {'x': 'abc'}, '/zzz/abc') + self.generates( + 'zzz/:x*traverse', {'x': 'abc', 'traverse': ''}, '/zzz/abc' + ) + self.generates( + 'zzz/:x*traverse', + {'x': 'abc', 'traverse': '/def/g'}, + '/zzz/abc/def/g', + ) + self.generates( + '/:x', + {'x': text_(b'/La Pe\xc3\xb1a', 'utf-8')}, + '//La%20Pe%C3%B1a', + ) + self.generates( + '/:x*y', + {'x': text_(b'/La Pe\xc3\xb1a', 'utf-8'), 'y': '/rest/of/path'}, + '//La%20Pe%C3%B1a/rest/of/path', + ) + self.generates( + '*traverse', + {'traverse': ('a', text_(b'La Pe\xf1a'))}, + '/a/La%20Pe%C3%B1a', + ) + self.generates('/foo/:id.html', {'id': 'bar'}, '/foo/bar.html') + self.generates('/foo/:_', {'_': '20'}, '/foo/20') + self.generates('/foo/:_abc', {'_abc': '20'}, '/foo/20') + self.generates('/foo/:abc_def', {'abc_def': '20'}, '/foo/20') + class DummyContext(object): """ """ - + + class DummyRequest(object): def __init__(self, environ): self.environ = environ - + + class DummyRoute(object): def __init__(self, generator): self.generate = generator - diff --git a/tests/test_util.py b/tests/test_util.py index 469cabadb..307c1a5f8 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,9 +1,5 @@ import unittest -from pyramid.compat import ( - PY2, - text_, - bytes_, - ) +from pyramid.compat import PY2, text_, bytes_ class Test_InstancePropertyHelper(unittest.TestCase): @@ -13,11 +9,13 @@ class Test_InstancePropertyHelper(unittest.TestCase): def _getTargetClass(self): from pyramid.util import InstancePropertyHelper + return InstancePropertyHelper def test_callable(self): def worker(obj): return obj.bar + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker) @@ -29,6 +27,7 @@ class Test_InstancePropertyHelper(unittest.TestCase): def test_callable_with_name(self): def worker(obj): return obj.bar + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker, name='x') @@ -40,6 +39,7 @@ class Test_InstancePropertyHelper(unittest.TestCase): def test_callable_with_reify(self): def worker(obj): return obj.bar + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker, reify=True) @@ -51,6 +51,7 @@ class Test_InstancePropertyHelper(unittest.TestCase): def test_callable_with_name_reify(self): def worker(obj): return obj.bar + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker, name='x') @@ -63,14 +64,19 @@ class Test_InstancePropertyHelper(unittest.TestCase): self.assertEqual(1, foo.y) def test_property_without_name(self): - def worker(obj): pass + def worker(obj): + pass + foo = Dummy() helper = self._getTargetClass() - self.assertRaises(ValueError, helper.set_property, foo, property(worker)) + self.assertRaises( + ValueError, helper.set_property, foo, property(worker) + ) def test_property_with_name(self): def worker(obj): return obj.bar + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, property(worker), name='x') @@ -80,23 +86,37 @@ class Test_InstancePropertyHelper(unittest.TestCase): self.assertEqual(2, foo.x) def test_property_with_reify(self): - def worker(obj): pass + def worker(obj): + pass + foo = Dummy() helper = self._getTargetClass() - self.assertRaises(ValueError, helper.set_property, - foo, property(worker), name='x', reify=True) + self.assertRaises( + ValueError, + helper.set_property, + foo, + property(worker), + name='x', + reify=True, + ) def test_override_property(self): - def worker(obj): pass + def worker(obj): + pass + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker, name='x') + def doit(): foo.x = 1 + self.assertRaises(AttributeError, doit) def test_override_reify(self): - def worker(obj): pass + def worker(obj): + pass + foo = Dummy() helper = self._getTargetClass() helper.set_property(foo, worker, name='x', reify=True) @@ -125,6 +145,7 @@ class Test_InstancePropertyHelper(unittest.TestCase): def test_make_property(self): from pyramid.decorator import reify + helper = self._getTargetClass() name, fn = helper.make_property(lambda x: 1, name='x', reify=True) self.assertEqual(name, 'x') @@ -188,21 +209,25 @@ class Test_InstancePropertyHelper(unittest.TestCase): self.assertEqual(foo.x, 1) self.assertEqual(bar.x, 2) + class Test_InstancePropertyMixin(unittest.TestCase): def _makeOne(self): cls = self._getTargetClass() class Foo(cls): pass + return Foo() def _getTargetClass(self): from pyramid.util import InstancePropertyMixin + return InstancePropertyMixin def test_callable(self): def worker(obj): return obj.bar + foo = self._makeOne() foo.set_property(worker) foo.bar = 1 @@ -213,6 +238,7 @@ class Test_InstancePropertyMixin(unittest.TestCase): def test_callable_with_name(self): def worker(obj): return obj.bar + foo = self._makeOne() foo.set_property(worker, name='x') foo.bar = 1 @@ -223,6 +249,7 @@ class Test_InstancePropertyMixin(unittest.TestCase): def test_callable_with_reify(self): def worker(obj): return obj.bar + foo = self._makeOne() foo.set_property(worker, reify=True) foo.bar = 1 @@ -233,6 +260,7 @@ class Test_InstancePropertyMixin(unittest.TestCase): def test_callable_with_name_reify(self): def worker(obj): return obj.bar + foo = self._makeOne() foo.set_property(worker, name='x') foo.set_property(worker, name='y', reify=True) @@ -244,13 +272,16 @@ class Test_InstancePropertyMixin(unittest.TestCase): self.assertEqual(1, foo.y) def test_property_without_name(self): - def worker(obj): pass + def worker(obj): + pass + foo = self._makeOne() self.assertRaises(ValueError, foo.set_property, property(worker)) def test_property_with_name(self): def worker(obj): return obj.bar + foo = self._makeOne() foo.set_property(property(worker), name='x') foo.bar = 1 @@ -259,21 +290,34 @@ class Test_InstancePropertyMixin(unittest.TestCase): self.assertEqual(2, foo.x) def test_property_with_reify(self): - def worker(obj): pass + def worker(obj): + pass + foo = self._makeOne() - self.assertRaises(ValueError, foo.set_property, - property(worker), name='x', reify=True) + self.assertRaises( + ValueError, + foo.set_property, + property(worker), + name='x', + reify=True, + ) def test_override_property(self): - def worker(obj): pass + def worker(obj): + pass + foo = self._makeOne() foo.set_property(worker, name='x') + def doit(): foo.x = 1 + self.assertRaises(AttributeError, doit) def test_override_reify(self): - def worker(obj): pass + def worker(obj): + pass + foo = self._makeOne() foo.set_property(worker, name='x', reify=True) foo.x = 1 @@ -305,9 +349,11 @@ class Test_InstancePropertyMixin(unittest.TestCase): self.assertEqual(foo.__module__, 'tests.test_util') self.assertEqual(foo.__class__.__module__, 'tests.test_util') + class Test_WeakOrderedSet(unittest.TestCase): def _makeOne(self): from pyramid.config import WeakOrderedSet + return WeakOrderedSet() def test_ctor(self): @@ -376,9 +422,11 @@ class Test_WeakOrderedSet(unittest.TestCase): self.assertEqual(list(wos), []) self.assertEqual(wos.last, None) + class Test_strings_differ(unittest.TestCase): def _callFUT(self, *args, **kw): from pyramid.util import strings_differ + return strings_differ(*args, **kw) def test_it_bytes(self): @@ -401,6 +449,7 @@ class Test_strings_differ(unittest.TestCase): def test_it_with_external_comparator(self): class DummyComparator(object): called = False + def __init__(self, ret_val): self.ret_val = ret_val @@ -423,9 +472,11 @@ class Test_strings_differ(unittest.TestCase): self.assertTrue(dummy_compare.called) self.assertTrue(result) + class Test_object_description(unittest.TestCase): def _callFUT(self, object): from pyramid.util import object_description + return object_description(object) def test_string(self): @@ -456,7 +507,7 @@ class Test_object_description(unittest.TestCase): self.assertEqual(self._callFUT(['a']), "['a']") def test_dict(self): - self.assertEqual(self._callFUT({'a':1}), "{'a': 1}") + self.assertEqual(self._callFUT({'a': 1}), "{'a': 1}") def test_nomodule(self): o = object() @@ -464,39 +515,40 @@ class Test_object_description(unittest.TestCase): def test_module(self): import pyramid + self.assertEqual(self._callFUT(pyramid), 'module pyramid') def test_method(self): self.assertEqual( self._callFUT(self.test_method), 'method test_method of class tests.test_util.' - 'Test_object_description') + 'Test_object_description', + ) def test_class(self): self.assertEqual( self._callFUT(self.__class__), - 'class tests.test_util.Test_object_description') + 'class tests.test_util.Test_object_description', + ) def test_function(self): self.assertEqual( - self._callFUT(dummyfunc), - 'function tests.test_util.dummyfunc') + self._callFUT(dummyfunc), 'function tests.test_util.dummyfunc' + ) def test_instance(self): inst = Dummy() - self.assertEqual( - self._callFUT(inst), - "object %s" % str(inst)) + self.assertEqual(self._callFUT(inst), "object %s" % str(inst)) def test_shortened_repr(self): inst = ['1'] * 1000 - self.assertEqual( - self._callFUT(inst), - str(inst)[:100] + ' ... ]') + self.assertEqual(self._callFUT(inst), str(inst)[:100] + ' ... ]') + class TestTopologicalSorter(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.util import TopologicalSorter + return TopologicalSorter(*arg, **kw) def test_remove(self): @@ -520,71 +572,72 @@ class TestTopologicalSorter(unittest.TestCase): def test_add(self): from pyramid.util import LAST + sorter = self._makeOne() sorter.add('name', 'factory') self.assertEqual(sorter.names, ['name']) - self.assertEqual(sorter.name2val, - {'name':'factory'}) + self.assertEqual(sorter.name2val, {'name': 'factory'}) self.assertEqual(sorter.order, [('name', LAST)]) sorter.add('name2', 'factory2') - self.assertEqual(sorter.names, ['name', 'name2']) - self.assertEqual(sorter.name2val, - {'name':'factory', 'name2':'factory2'}) - self.assertEqual(sorter.order, - [('name', LAST), ('name2', LAST)]) + self.assertEqual(sorter.names, ['name', 'name2']) + self.assertEqual( + sorter.name2val, {'name': 'factory', 'name2': 'factory2'} + ) + self.assertEqual(sorter.order, [('name', LAST), ('name2', LAST)]) sorter.add('name3', 'factory3', before='name2') - self.assertEqual(sorter.names, - ['name', 'name2', 'name3']) - self.assertEqual(sorter.name2val, - {'name':'factory', 'name2':'factory2', - 'name3':'factory3'}) - self.assertEqual(sorter.order, - [('name', LAST), ('name2', LAST), - ('name3', 'name2')]) + self.assertEqual(sorter.names, ['name', 'name2', 'name3']) + self.assertEqual( + sorter.name2val, + {'name': 'factory', 'name2': 'factory2', 'name3': 'factory3'}, + ) + self.assertEqual( + sorter.order, [('name', LAST), ('name2', LAST), ('name3', 'name2')] + ) def test_sorted_ordering_1(self): sorter = self._makeOne() sorter.add('name1', 'factory1') sorter.add('name2', 'factory2') - self.assertEqual(sorter.sorted(), - [ - ('name1', 'factory1'), - ('name2', 'factory2'), - ]) + self.assertEqual( + sorter.sorted(), [('name1', 'factory1'), ('name2', 'factory2')] + ) def test_sorted_ordering_2(self): from pyramid.util import FIRST + sorter = self._makeOne() sorter.add('name1', 'factory1') sorter.add('name2', 'factory2', after=FIRST) - self.assertEqual(sorter.sorted(), - [ - ('name2', 'factory2'), - ('name1', 'factory1'), - ]) + self.assertEqual( + sorter.sorted(), [('name2', 'factory2'), ('name1', 'factory1')] + ) def test_sorted_ordering_3(self): from pyramid.util import FIRST + sorter = self._makeOne() add = sorter.add add('auth', 'auth_factory', after='browserid') - add('dbt', 'dbt_factory') + add('dbt', 'dbt_factory') add('retry', 'retry_factory', before='txnmgr', after='exceptionview') add('browserid', 'browserid_factory') add('txnmgr', 'txnmgr_factory', after='exceptionview') add('exceptionview', 'excview_factory', after=FIRST) - self.assertEqual(sorter.sorted(), - [ - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ('dbt', 'dbt_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ]) + self.assertEqual( + sorter.sorted(), + [ + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ('dbt', 'dbt_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ], + ) def test_sorted_ordering_4(self): from pyramid.util import FIRST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', after=FIRST) @@ -592,19 +645,22 @@ class TestTopologicalSorter(unittest.TestCase): add('retry', 'retry_factory', before='txnmgr', after='exceptionview') add('browserid', 'browserid_factory') add('txnmgr', 'txnmgr_factory', after='exceptionview') - add('dbt', 'dbt_factory') - self.assertEqual(sorter.sorted(), - [ - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('dbt', 'dbt_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + sorter.sorted(), + [ + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('dbt', 'dbt_factory'), + ], + ) def test_sorted_ordering_5(self): from pyramid.util import LAST, FIRST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory') @@ -612,19 +668,22 @@ class TestTopologicalSorter(unittest.TestCase): add('retry', 'retry_factory', before='txnmgr', after='exceptionview') add('browserid', 'browserid_factory', after=FIRST) add('txnmgr', 'txnmgr_factory', after='exceptionview', before=LAST) - add('dbt', 'dbt_factory') - self.assertEqual(sorter.sorted(), - [ - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('txnmgr', 'txnmgr_factory'), - ('dbt', 'dbt_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + sorter.sorted(), + [ + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('txnmgr', 'txnmgr_factory'), + ('dbt', 'dbt_factory'), + ], + ) def test_sorted_ordering_missing_before_partial(self): from pyramid.exceptions import ConfigurationError + sorter = self._makeOne() add = sorter.add add('dbt', 'dbt_factory') @@ -635,6 +694,7 @@ class TestTopologicalSorter(unittest.TestCase): def test_sorted_ordering_missing_after_partial(self): from pyramid.exceptions import ConfigurationError + sorter = self._makeOne() add = sorter.add add('dbt', 'dbt_factory') @@ -645,6 +705,7 @@ class TestTopologicalSorter(unittest.TestCase): def test_sorted_ordering_missing_before_and_after_partials(self): from pyramid.exceptions import ConfigurationError + sorter = self._makeOne() add = sorter.add add('dbt', 'dbt_factory') @@ -655,72 +716,93 @@ class TestTopologicalSorter(unittest.TestCase): def test_sorted_ordering_missing_before_partial_with_fallback(self): from pyramid.util import LAST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', before=LAST) add('auth', 'auth_factory', after='browserid') - add('retry', 'retry_factory', before=('txnmgr', LAST), - after='exceptionview') + add( + 'retry', + 'retry_factory', + before=('txnmgr', LAST), + after='exceptionview', + ) add('browserid', 'browserid_factory') - add('dbt', 'dbt_factory') - self.assertEqual(sorter.sorted(), - [ - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('dbt', 'dbt_factory'), - ]) + add('dbt', 'dbt_factory') + self.assertEqual( + sorter.sorted(), + [ + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('dbt', 'dbt_factory'), + ], + ) def test_sorted_ordering_missing_after_partial_with_fallback(self): from pyramid.util import FIRST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', after=FIRST) - add('auth', 'auth_factory', after=('txnmgr','browserid')) + add('auth', 'auth_factory', after=('txnmgr', 'browserid')) add('retry', 'retry_factory', after='exceptionview') add('browserid', 'browserid_factory') add('dbt', 'dbt_factory') - self.assertEqual(sorter.sorted(), - [ - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ('browserid', 'browserid_factory'), - ('auth', 'auth_factory'), - ('dbt', 'dbt_factory'), - ]) + self.assertEqual( + sorter.sorted(), + [ + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ('browserid', 'browserid_factory'), + ('auth', 'auth_factory'), + ('dbt', 'dbt_factory'), + ], + ) def test_sorted_ordering_with_partial_fallbacks(self): from pyramid.util import LAST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', before=('wontbethere', LAST)) add('retry', 'retry_factory', after='exceptionview') - add('browserid', 'browserid_factory', before=('wont2', 'exceptionview')) - self.assertEqual(sorter.sorted(), - [ - ('browserid', 'browserid_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + add( + 'browserid', 'browserid_factory', before=('wont2', 'exceptionview') + ) + self.assertEqual( + sorter.sorted(), + [ + ('browserid', 'browserid_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_sorted_ordering_with_multiple_matching_fallbacks(self): from pyramid.util import LAST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', before=LAST) add('retry', 'retry_factory', after='exceptionview') - add('browserid', 'browserid_factory', before=('retry', 'exceptionview')) - self.assertEqual(sorter.sorted(), - [ - ('browserid', 'browserid_factory'), - ('exceptionview', 'excview_factory'), - ('retry', 'retry_factory'), - ]) + add( + 'browserid', 'browserid_factory', before=('retry', 'exceptionview') + ) + self.assertEqual( + sorter.sorted(), + [ + ('browserid', 'browserid_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ], + ) def test_sorted_ordering_with_missing_fallbacks(self): from pyramid.exceptions import ConfigurationError from pyramid.util import LAST + sorter = self._makeOne() add = sorter.add add('exceptionview', 'excview_factory', before=LAST) @@ -730,6 +812,7 @@ class TestTopologicalSorter(unittest.TestCase): def test_sorted_ordering_conflict_direct(self): from pyramid.exceptions import CyclicDependencyError + sorter = self._makeOne() add = sorter.add add('browserid', 'browserid_factory') @@ -738,6 +821,7 @@ class TestTopologicalSorter(unittest.TestCase): def test_sorted_ordering_conflict_indirect(self): from pyramid.exceptions import CyclicDependencyError + sorter = self._makeOne() add = sorter.add add('browserid', 'browserid_factory') @@ -745,9 +829,11 @@ class TestTopologicalSorter(unittest.TestCase): add('dbt', 'dbt_factory', after='browserid', before='auth') self.assertRaises(CyclicDependencyError, sorter.sorted) + class TestSentinel(unittest.TestCase): def test_repr(self): from pyramid.util import Sentinel + r = repr(Sentinel('ABC')) self.assertEqual(r, 'ABC') @@ -783,16 +869,19 @@ class TestCallableName(unittest.TestCase): class Test_hide_attrs(unittest.TestCase): def _callFUT(self, obj, *attrs): from pyramid.util import hide_attrs + return hide_attrs(obj, *attrs) def _makeDummy(self): from pyramid.decorator import reify + class Dummy(object): x = 1 @reify def foo(self): return self.x + return Dummy() def test_restores_attrs(self): @@ -814,7 +903,7 @@ class Test_hide_attrs(unittest.TestCase): raise RuntimeError() except RuntimeError: self.assertEqual(obj.foo, orig_foo) - else: # pragma: no cover + else: # pragma: no cover self.fail("RuntimeError not raised") def test_restores_attrs_to_none(self): @@ -837,7 +926,8 @@ class Test_hide_attrs(unittest.TestCase): self.assertTrue('foo' not in obj.__dict__) -def dummyfunc(): pass +def dummyfunc(): + pass class Dummy(object): @@ -847,6 +937,7 @@ class Dummy(object): class Test_is_same_domain(unittest.TestCase): def _callFUT(self, *args, **kw): from pyramid.util import is_same_domain + return is_same_domain(*args, **kw) def test_it(self): @@ -868,6 +959,7 @@ class Test_is_same_domain(unittest.TestCase): class Test_make_contextmanager(unittest.TestCase): def _callFUT(self, *args, **kw): from pyramid.util import make_contextmanager + return make_contextmanager(*args, **kw) def test_with_None(self): @@ -878,6 +970,7 @@ class Test_make_contextmanager(unittest.TestCase): def test_with_generator(self): def mygen(ctx): yield ctx + mgr = self._callFUT(mygen) with mgr('a') as ctx: self.assertEqual(ctx, 'a') @@ -886,6 +979,7 @@ class Test_make_contextmanager(unittest.TestCase): def mygen(): yield 'a' yield 'b' + mgr = self._callFUT(mygen) try: with mgr() as ctx: @@ -898,6 +992,7 @@ class Test_make_contextmanager(unittest.TestCase): def test_with_regular_fn(self): def mygen(): return 'a' + mgr = self._callFUT(mygen) with mgr() as ctx: self.assertEqual(ctx, 'a') @@ -906,146 +1001,173 @@ class Test_make_contextmanager(unittest.TestCase): class Test_takes_one_arg(unittest.TestCase): def _callFUT(self, view, attr=None, argname=None): from pyramid.util import takes_one_arg + return takes_one_arg(view, attr=attr, argname=argname) def test_requestonly_newstyle_class_no_init(self): class foo(object): """ """ + self.assertFalse(self._callFUT(foo)) def test_requestonly_newstyle_class_init_toomanyargs(self): class foo(object): def __init__(self, context, request): """ """ + self.assertFalse(self._callFUT(foo)) def test_requestonly_newstyle_class_init_onearg_named_request(self): class foo(object): def __init__(self, request): """ """ + self.assertTrue(self._callFUT(foo)) def test_newstyle_class_init_onearg_named_somethingelse(self): class foo(object): def __init__(self, req): """ """ + self.assertTrue(self._callFUT(foo)) def test_newstyle_class_init_defaultargs_firstname_not_request(self): class foo(object): def __init__(self, context, request=None): """ """ + self.assertFalse(self._callFUT(foo)) def test_newstyle_class_init_defaultargs_firstname_request(self): class foo(object): def __init__(self, request, foo=1, bar=2): """ """ + self.assertTrue(self._callFUT(foo, argname='request')) def test_newstyle_class_init_firstname_request_with_secondname(self): class foo(object): def __init__(self, request, two): """ """ + self.assertFalse(self._callFUT(foo)) def test_newstyle_class_init_noargs(self): class foo(object): def __init__(): """ """ + self.assertFalse(self._callFUT(foo)) def test_oldstyle_class_no_init(self): class foo: """ """ + self.assertFalse(self._callFUT(foo)) def test_oldstyle_class_init_toomanyargs(self): class foo: def __init__(self, context, request): """ """ + self.assertFalse(self._callFUT(foo)) def test_oldstyle_class_init_onearg_named_request(self): class foo: def __init__(self, request): """ """ + self.assertTrue(self._callFUT(foo)) def test_oldstyle_class_init_onearg_named_somethingelse(self): class foo: def __init__(self, req): """ """ + self.assertTrue(self._callFUT(foo)) def test_oldstyle_class_init_defaultargs_firstname_not_request(self): class foo: def __init__(self, context, request=None): """ """ + self.assertFalse(self._callFUT(foo)) def test_oldstyle_class_init_defaultargs_firstname_request(self): class foo: def __init__(self, request, foo=1, bar=2): """ """ + self.assertTrue(self._callFUT(foo, argname='request'), True) def test_oldstyle_class_init_noargs(self): class foo: def __init__(): """ """ + self.assertFalse(self._callFUT(foo)) def test_function_toomanyargs(self): def foo(context, request): """ """ + self.assertFalse(self._callFUT(foo)) def test_function_with_attr_false(self): def bar(context, request): """ """ + def foo(context, request): """ """ + foo.bar = bar self.assertFalse(self._callFUT(foo, 'bar')) def test_function_with_attr_true(self): def bar(context, request): """ """ + def foo(request): """ """ + foo.bar = bar self.assertTrue(self._callFUT(foo, 'bar')) def test_function_onearg_named_request(self): def foo(request): """ """ + self.assertTrue(self._callFUT(foo)) def test_function_onearg_named_somethingelse(self): def foo(req): """ """ + self.assertTrue(self._callFUT(foo)) def test_function_defaultargs_firstname_not_request(self): def foo(context, request=None): """ """ + self.assertFalse(self._callFUT(foo)) def test_function_defaultargs_firstname_request(self): def foo(request, foo=1, bar=2): """ """ + self.assertTrue(self._callFUT(foo, argname='request')) def test_function_noargs(self): def foo(): """ """ + self.assertFalse(self._callFUT(foo)) def test_instance_toomanyargs(self): class Foo: def __call__(self, context, request): """ """ + foo = Foo() self.assertFalse(self._callFUT(foo)) @@ -1053,6 +1175,7 @@ class Test_takes_one_arg(unittest.TestCase): class Foo: def __call__(self, request): """ """ + foo = Foo() self.assertTrue(self._callFUT(foo)) @@ -1060,6 +1183,7 @@ class Test_takes_one_arg(unittest.TestCase): class Foo: def __call__(self, req): """ """ + foo = Foo() self.assertTrue(self._callFUT(foo)) @@ -1067,6 +1191,7 @@ class Test_takes_one_arg(unittest.TestCase): class Foo: def __call__(self, context, request=None): """ """ + foo = Foo() self.assertFalse(self._callFUT(foo)) @@ -1074,11 +1199,14 @@ class Test_takes_one_arg(unittest.TestCase): class Foo: def __call__(self, request, foo=1, bar=2): """ """ + foo = Foo() self.assertTrue(self._callFUT(foo, argname='request'), True) def test_instance_nocall(self): - class Foo: pass + class Foo: + pass + foo = Foo() self.assertFalse(self._callFUT(foo)) @@ -1086,12 +1214,14 @@ class Test_takes_one_arg(unittest.TestCase): class Foo: def method(self, request): """ """ + foo = Foo() self.assertTrue(self._callFUT(foo.method)) def test_function_annotations(self): def foo(bar): """ """ + # avoid SyntaxErrors in python2, this if effectively nop getattr(foo, '__annotations__', {}).update({'bar': 'baz'}) self.assertTrue(self._callFUT(foo)) @@ -1100,6 +1230,7 @@ class Test_takes_one_arg(unittest.TestCase): class TestSimpleSerializer(unittest.TestCase): def _makeOne(self): from pyramid.util import SimpleSerializer + return SimpleSerializer() def test_loads(self): diff --git a/tests/test_view.py b/tests/test_view.py index 279777f89..039605408 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -7,6 +7,7 @@ from pyramid import testing from pyramid.interfaces import IRequest + class BaseTest(object): def setUp(self): self.config = testing.setUp() @@ -16,25 +17,28 @@ class BaseTest(object): def _registerView(self, reg, app, name): from pyramid.interfaces import IViewClassifier + for_ = (IViewClassifier, IRequest, IContext) from pyramid.interfaces import IView + reg.registerAdapter(app, for_, IView, name) def _makeEnviron(self, **extras): environ = { - 'wsgi.url_scheme':'http', - 'wsgi.version':(1,0), - 'SERVER_NAME':'localhost', - 'SERVER_PORT':'8080', - 'REQUEST_METHOD':'GET', - 'PATH_INFO':'/', - } + 'wsgi.url_scheme': 'http', + 'wsgi.version': (1, 0), + 'SERVER_NAME': 'localhost', + 'SERVER_PORT': '8080', + 'REQUEST_METHOD': 'GET', + 'PATH_INFO': '/', + } environ.update(extras) return environ def _makeRequest(self, **environ): from pyramid.request import Request from pyramid.registry import Registry + environ = self._makeEnviron(**environ) request = Request(environ) request.registry = Registry() @@ -42,26 +46,34 @@ class BaseTest(object): def _makeContext(self): from zope.interface import directlyProvides + context = DummyContext() directlyProvides(context, IContext) return context + class Test_notfound_view_config(BaseTest, unittest.TestCase): def _makeOne(self, **kw): from pyramid.view import notfound_view_config + return notfound_view_config(**kw) def test_ctor(self): - inst = self._makeOne(attr='attr', path_info='path_info', - append_slash=True) - self.assertEqual(inst.__dict__, - {'attr':'attr', 'path_info':'path_info', - 'append_slash':True}) + inst = self._makeOne( + attr='attr', path_info='path_info', append_slash=True + ) + self.assertEqual( + inst.__dict__, + {'attr': 'attr', 'path_info': 'path_info', 'append_slash': True}, + ) def test_it_function(self): - def view(request): pass - decorator = self._makeOne(attr='attr', renderer='renderer', - append_slash=True) + def view(request): + pass + + decorator = self._makeOne( + attr='attr', renderer='renderer', append_slash=True + ) venusian = DummyVenusian() decorator.venusian = venusian wrapped = decorator(view) @@ -69,17 +81,28 @@ class Test_notfound_view_config(BaseTest, unittest.TestCase): config = call_venusian(venusian) settings = config.settings self.assertEqual( - settings, - [{'attr': 'attr', 'venusian': venusian, 'append_slash': True, - 'renderer': 'renderer', '_info': 'codeinfo', 'view': None}] - ) + settings, + [ + { + 'attr': 'attr', + 'venusian': venusian, + 'append_slash': True, + 'renderer': 'renderer', + '_info': 'codeinfo', + 'view': None, + } + ], + ) def test_it_class(self): decorator = self._makeOne() venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - class view(object): pass + + class view(object): + pass + wrapped = decorator(view) self.assertTrue(wrapped is view) config = call_venusian(venusian) @@ -87,7 +110,7 @@ class Test_notfound_view_config(BaseTest, unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 4) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'view') self.assertEqual(settings[0]['_info'], 'codeinfo') @@ -95,7 +118,10 @@ class Test_notfound_view_config(BaseTest, unittest.TestCase): decorator = self._makeOne(_depth=1, _category='foo') venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments category = attachments[0][2] @@ -103,18 +129,23 @@ class Test_notfound_view_config(BaseTest, unittest.TestCase): self.assertEqual(depth, 2) self.assertEqual(category, 'foo') + class Test_forbidden_view_config(BaseTest, unittest.TestCase): def _makeOne(self, **kw): from pyramid.view import forbidden_view_config + return forbidden_view_config(**kw) def test_ctor(self): inst = self._makeOne(attr='attr', path_info='path_info') - self.assertEqual(inst.__dict__, - {'attr':'attr', 'path_info':'path_info'}) + self.assertEqual( + inst.__dict__, {'attr': 'attr', 'path_info': 'path_info'} + ) def test_it_function(self): - def view(request): pass + def view(request): + pass + decorator = self._makeOne(attr='attr', renderer='renderer') venusian = DummyVenusian() decorator.venusian = venusian @@ -123,17 +154,27 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase): config = call_venusian(venusian) settings = config.settings self.assertEqual( - settings, - [{'attr': 'attr', 'venusian': venusian, - 'renderer': 'renderer', '_info': 'codeinfo', 'view': None}] - ) + settings, + [ + { + 'attr': 'attr', + 'venusian': venusian, + 'renderer': 'renderer', + '_info': 'codeinfo', + 'view': None, + } + ], + ) def test_it_class(self): decorator = self._makeOne() venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - class view(object): pass + + class view(object): + pass + wrapped = decorator(view) self.assertTrue(wrapped is view) config = call_venusian(venusian) @@ -141,7 +182,7 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 4) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'view') self.assertEqual(settings[0]['_info'], 'codeinfo') @@ -149,7 +190,10 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase): decorator = self._makeOne(_depth=1, _category='foo') venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments category = attachments[0][2] @@ -157,27 +201,36 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase): self.assertEqual(depth, 2) self.assertEqual(category, 'foo') + class Test_exception_view_config(BaseTest, unittest.TestCase): def _makeOne(self, *args, **kw): from pyramid.view import exception_view_config + return exception_view_config(*args, **kw) def test_ctor(self): inst = self._makeOne(context=Exception, path_info='path_info') - self.assertEqual(inst.__dict__, - {'context':Exception, 'path_info':'path_info'}) + self.assertEqual( + inst.__dict__, {'context': Exception, 'path_info': 'path_info'} + ) def test_ctor_positional_exception(self): inst = self._makeOne(Exception, path_info='path_info') - self.assertEqual(inst.__dict__, - {'context':Exception, 'path_info':'path_info'}) + self.assertEqual( + inst.__dict__, {'context': Exception, 'path_info': 'path_info'} + ) def test_ctor_positional_extras(self): from pyramid.exceptions import ConfigurationError - self.assertRaises(ConfigurationError, lambda: self._makeOne(Exception, True)) + + self.assertRaises( + ConfigurationError, lambda: self._makeOne(Exception, True) + ) def test_it_function(self): - def view(request): pass + def view(request): + pass + decorator = self._makeOne(context=Exception, renderer='renderer') venusian = DummyVenusian() decorator.venusian = venusian @@ -187,16 +240,26 @@ class Test_exception_view_config(BaseTest, unittest.TestCase): settings = config.settings self.assertEqual( settings, - [{'venusian': venusian, 'context': Exception, - 'renderer': 'renderer', '_info': 'codeinfo', 'view': None}] - ) + [ + { + 'venusian': venusian, + 'context': Exception, + 'renderer': 'renderer', + '_info': 'codeinfo', + 'view': None, + } + ], + ) def test_it_class(self): decorator = self._makeOne() venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - class view(object): pass + + class view(object): + pass + wrapped = decorator(view) self.assertTrue(wrapped is view) config = call_venusian(venusian) @@ -204,7 +267,7 @@ class Test_exception_view_config(BaseTest, unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 4) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'view') self.assertEqual(settings[0]['_info'], 'codeinfo') @@ -212,7 +275,10 @@ class Test_exception_view_config(BaseTest, unittest.TestCase): decorator = self._makeOne(_depth=1, _category='foo') venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments category = attachments[0][2] @@ -220,11 +286,13 @@ class Test_exception_view_config(BaseTest, unittest.TestCase): self.assertEqual(depth, 2) self.assertEqual(category, 'foo') + class RenderViewToResponseTests(BaseTest, unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.view import render_view_to_response + return render_view_to_response(*arg, **kw) - + def test_call_no_view_registered(self): request = self._makeRequest() context = self._makeContext() @@ -244,8 +312,9 @@ class RenderViewToResponseTests(BaseTest, unittest.TestCase): response = DummyResponse() view = make_view(response) self._registerView(request.registry, view, 'registered') - response = self._callFUT(context, request, name='registered', - secure=True) + response = self._callFUT( + context, request, name='registered', secure=True + ) self.assertEqual(response.status, '200 OK') def test_call_view_registered_insecure_no_call_permissive(self): @@ -254,8 +323,9 @@ class RenderViewToResponseTests(BaseTest, unittest.TestCase): response = DummyResponse() view = make_view(response) self._registerView(request.registry, view, 'registered') - response = self._callFUT(context, request, name='registered', - secure=False) + response = self._callFUT( + context, request, name='registered', secure=False + ) self.assertEqual(response.status, '200 OK') def test_call_view_registered_insecure_with_call_permissive(self): @@ -263,19 +333,25 @@ class RenderViewToResponseTests(BaseTest, unittest.TestCase): request = self._makeRequest() response = DummyResponse() view = make_view(response) + def anotherview(context, request): return DummyResponse('anotherview') + view.__call_permissive__ = anotherview self._registerView(request.registry, view, 'registered') - response = self._callFUT(context, request, name='registered', - secure=False) + response = self._callFUT( + context, request, name='registered', secure=False + ) self.assertEqual(response.status, '200 OK') self.assertEqual(response.app_iter, ['anotherview']) def test_call_view_with_request_iface_on_request(self): # See https://github.com/Pylons/pyramid/issues/1643 from zope.interface import Interface - class IWontBeFound(Interface): pass + + class IWontBeFound(Interface): + pass + context = self._makeContext() request = self._makeRequest() request.request_iface = IWontBeFound @@ -286,11 +362,13 @@ class RenderViewToResponseTests(BaseTest, unittest.TestCase): self.assertEqual(response.status, '200 OK') self.assertEqual(response.app_iter, ['aview']) + class RenderViewToIterableTests(BaseTest, unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.view import render_view_to_iterable + return render_view_to_iterable(*arg, **kw) - + def test_call_no_view_registered(self): request = self._makeRequest() context = self._makeContext() @@ -303,8 +381,9 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): response = DummyResponse() view = make_view(response) self._registerView(request.registry, view, 'registered') - iterable = self._callFUT(context, request, name='registered', - secure=True) + iterable = self._callFUT( + context, request, name='registered', secure=True + ) self.assertEqual(iterable, ()) def test_call_view_registered_insecure_no_call_permissive(self): @@ -313,8 +392,9 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): response = DummyResponse() view = make_view(response) self._registerView(request.registry, view, 'registered') - iterable = self._callFUT(context, request, name='registered', - secure=False) + iterable = self._callFUT( + context, request, name='registered', secure=False + ) self.assertEqual(iterable, ()) def test_call_view_registered_insecure_with_call_permissive(self): @@ -322,12 +402,15 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): request = self._makeRequest() response = DummyResponse() view = make_view(response) + def anotherview(context, request): return DummyResponse(b'anotherview') + view.__call_permissive__ = anotherview self._registerView(request.registry, view, 'registered') - iterable = self._callFUT(context, request, name='registered', - secure=False) + iterable = self._callFUT( + context, request, name='registered', secure=False + ) self.assertEqual(iterable, [b'anotherview']) def test_verify_output_bytestring(self): @@ -335,7 +418,9 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): from pyramid.config import Configurator from pyramid.view import render_view from webob.compat import text_type + config = Configurator(settings={}) + def view(request): request.response.text = text_type('<body></body>') return request.response @@ -355,15 +440,18 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): response = DummyResponse() view = make_view(response) self._registerView(registry, view, 'registered') - iterable = self._callFUT(context, request, name='registered', - secure=True) + iterable = self._callFUT( + context, request, name='registered', secure=True + ) self.assertEqual(iterable, ()) + class RenderViewTests(BaseTest, unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.view import render_view + return render_view(*arg, **kw) - + def test_call_no_view_registered(self): request = self._makeRequest() context = self._makeContext() @@ -393,13 +481,16 @@ class RenderViewTests(BaseTest, unittest.TestCase): request = self._makeRequest() response = DummyResponse() view = make_view(response) + def anotherview(context, request): return DummyResponse(b'anotherview') + view.__call_permissive__ = anotherview self._registerView(request.registry, view, 'registered') s = self._callFUT(context, request, name='registered', secure=False) self.assertEqual(s, b'anotherview') + class TestViewConfigDecorator(unittest.TestCase): def setUp(self): testing.setUp() @@ -409,6 +500,7 @@ class TestViewConfigDecorator(unittest.TestCase): def _getTargetClass(self): from pyramid.view import view_config + return view_config def _makeOne(self, *arg, **kw): @@ -425,13 +517,17 @@ class TestViewConfigDecorator(unittest.TestCase): def test_create_for_trumps_context_None(self): decorator = self._makeOne(context=None, for_='456') self.assertEqual(decorator.context, '456') - + def test_create_nondefaults(self): decorator = self._makeOne( - name=None, request_type=None, for_=None, - permission='foo', mapper='mapper', - decorator='decorator', match_param='match_param' - ) + name=None, + request_type=None, + for_=None, + permission='foo', + mapper='mapper', + decorator='decorator', + match_param='match_param', + ) self.assertEqual(decorator.name, None) self.assertEqual(decorator.request_type, None) self.assertEqual(decorator.context, None) @@ -447,12 +543,15 @@ class TestViewConfigDecorator(unittest.TestCase): def test_create_decorator_tuple(self): decorator = self._makeOne(decorator=('decorator1', 'decorator2')) self.assertEqual(decorator.decorator, ('decorator1', 'decorator2')) - + def test_call_function(self): decorator = self._makeOne() venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) config = call_venusian(venusian) @@ -461,7 +560,7 @@ class TestViewConfigDecorator(unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 3) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['_info'], 'codeinfo') def test_call_class(self): @@ -469,7 +568,10 @@ class TestViewConfigDecorator(unittest.TestCase): venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - class foo(object): pass + + class foo(object): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) config = call_venusian(venusian) @@ -477,7 +579,7 @@ class TestViewConfigDecorator(unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 4) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'foo') self.assertEqual(settings[0]['_info'], 'codeinfo') @@ -486,7 +588,10 @@ class TestViewConfigDecorator(unittest.TestCase): venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - class foo(object): pass + + class foo(object): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) config = call_venusian(venusian) @@ -494,7 +599,7 @@ class TestViewConfigDecorator(unittest.TestCase): self.assertEqual(len(settings), 1) self.assertEqual(len(settings[0]), 4) self.assertEqual(settings[0]['venusian'], venusian) - self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'abc') self.assertEqual(settings[0]['_info'], 'codeinfo') @@ -505,7 +610,10 @@ class TestViewConfigDecorator(unittest.TestCase): venusian2 = DummyVenusian() decorator2 = self._makeOne(name='2') decorator2.venusian = venusian2 - def foo(): pass + + def foo(): + pass + wrapped1 = decorator1(foo) wrapped2 = decorator2(wrapped1) self.assertTrue(wrapped1 is foo) @@ -522,11 +630,17 @@ class TestViewConfigDecorator(unittest.TestCase): venusian = DummyVenusian() decorator.venusian = venusian decorator.venusian.info.scope = 'class' - def foo(self): pass - def bar(self): pass + + def foo(self): + pass + + def bar(self): + pass + class foo(object): foomethod = decorator(foo) barmethod = decorator(bar) + config = call_venusian(venusian) settings = config.settings self.assertEqual(len(settings), 2) @@ -537,7 +651,10 @@ class TestViewConfigDecorator(unittest.TestCase): decorator = self._makeOne(custom_predicates=(1,)) venusian = DummyVenusian() decorator.venusian = venusian - def foo(context, request): pass + + def foo(context, request): + pass + decorated = decorator(foo) self.assertTrue(decorated is foo) config = call_venusian(venusian) @@ -546,10 +663,14 @@ class TestViewConfigDecorator(unittest.TestCase): def test_call_with_renderer_string(self): import tests + decorator = self._makeOne(renderer='fixtures/minimal.pt') venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) config = call_venusian(venusian) @@ -561,29 +682,38 @@ class TestViewConfigDecorator(unittest.TestCase): def test_call_with_renderer_dict(self): import tests - decorator = self._makeOne(renderer={'a':1}) + + decorator = self._makeOne(renderer={'a': 1}) venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) config = call_venusian(venusian) settings = config.settings self.assertEqual(len(settings), 1) - self.assertEqual(settings[0]['renderer'], {'a':1}) + self.assertEqual(settings[0]['renderer'], {'a': 1}) self.assertEqual(config.pkg, tests) def test_call_with_renderer_IRendererInfo(self): import tests from pyramid.interfaces import IRendererInfo + @implementer(IRendererInfo) class DummyRendererHelper(object): pass + renderer_helper = DummyRendererHelper() decorator = self._makeOne(renderer=renderer_helper) venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + wrapped = decorator(foo) self.assertTrue(wrapped is foo) context = DummyVenusianContext() @@ -598,7 +728,10 @@ class TestViewConfigDecorator(unittest.TestCase): decorator = self._makeOne(_depth=1) venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments depth = attachments[0][3] @@ -608,7 +741,10 @@ class TestViewConfigDecorator(unittest.TestCase): decorator = self._makeOne() venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments category = attachments[0][2] @@ -618,29 +754,39 @@ class TestViewConfigDecorator(unittest.TestCase): decorator = self._makeOne(_category='not_pyramid') venusian = DummyVenusian() decorator.venusian = venusian - def foo(): pass + + def foo(): + pass + decorator(foo) attachments = venusian.attachments category = attachments[0][2] self.assertEqual(category, 'not_pyramid') + class Test_append_slash_notfound_view(BaseTest, unittest.TestCase): def _callFUT(self, context, request): from pyramid.view import append_slash_notfound_view + return append_slash_notfound_view(context, request) def _registerMapper(self, reg, match=True): from pyramid.interfaces import IRoutesMapper + class DummyRoute(object): def __init__(self, val): self.val = val + def match(self, path): return self.val + class DummyMapper(object): def __init__(self): - self.routelist = [ DummyRoute(match) ] + self.routelist = [DummyRoute(match)] + def get_routes(self): return self.routelist + mapper = DummyMapper() reg.registerUtility(mapper, IRoutesMapper) return mapper @@ -705,23 +851,29 @@ class Test_append_slash_notfound_view(BaseTest, unittest.TestCase): self.assertEqual(response.status, '307 Temporary Redirect') self.assertEqual(response.location, '/abc/?a=1&b=2') + class TestAppendSlashNotFoundViewFactory(BaseTest, unittest.TestCase): def _makeOne(self, notfound_view): from pyramid.view import AppendSlashNotFoundViewFactory + return AppendSlashNotFoundViewFactory(notfound_view) - + def test_custom_notfound_view(self): request = self._makeRequest(PATH_INFO='/abc') context = ExceptionResponse() + def custom_notfound(context, request): return 'OK' + view = self._makeOne(custom_notfound) response = view(context, request) self.assertEqual(response, 'OK') + class Test_default_exceptionresponse_view(unittest.TestCase): def _callFUT(self, context, request): from pyramid.view import default_exceptionresponse_view + return default_exceptionresponse_view(context, request) def test_is_exception(self): @@ -749,39 +901,59 @@ class Test_default_exceptionresponse_view(unittest.TestCase): result = self._callFUT(context, request) self.assertEqual(result, 'abc') + class Test_view_defaults(unittest.TestCase): def test_it(self): from pyramid.view import view_defaults + @view_defaults(route_name='abc', renderer='def') - class Foo(object): pass - self.assertEqual(Foo.__view_defaults__['route_name'],'abc') - self.assertEqual(Foo.__view_defaults__['renderer'],'def') + class Foo(object): + pass + + self.assertEqual(Foo.__view_defaults__['route_name'], 'abc') + self.assertEqual(Foo.__view_defaults__['renderer'], 'def') def test_it_inheritance_not_overridden(self): from pyramid.view import view_defaults + @view_defaults(route_name='abc', renderer='def') - class Foo(object): pass - class Bar(Foo): pass - self.assertEqual(Bar.__view_defaults__['route_name'],'abc') - self.assertEqual(Bar.__view_defaults__['renderer'],'def') + class Foo(object): + pass + + class Bar(Foo): + pass + + self.assertEqual(Bar.__view_defaults__['route_name'], 'abc') + self.assertEqual(Bar.__view_defaults__['renderer'], 'def') def test_it_inheritance_overriden(self): from pyramid.view import view_defaults + @view_defaults(route_name='abc', renderer='def') - class Foo(object): pass + class Foo(object): + pass + @view_defaults(route_name='ghi') - class Bar(Foo): pass - self.assertEqual(Bar.__view_defaults__['route_name'],'ghi') + class Bar(Foo): + pass + + self.assertEqual(Bar.__view_defaults__['route_name'], 'ghi') self.assertFalse('renderer' in Bar.__view_defaults__) def test_it_inheritance_overriden_empty(self): from pyramid.view import view_defaults + @view_defaults(route_name='abc', renderer='def') - class Foo(object): pass + class Foo(object): + pass + @view_defaults() - class Bar(Foo): pass + class Bar(Foo): + pass + self.assertEqual(Bar.__view_defaults__, {}) + class TestViewMethodsMixin(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -792,8 +964,10 @@ class TestViewMethodsMixin(unittest.TestCase): def _makeOne(self, environ=None): from pyramid.decorator import reify from pyramid.view import ViewMethodsMixin + if environ is None: environ = {} + class Request(ViewMethodsMixin): def __init__(self, environ): self.environ = environ @@ -801,6 +975,7 @@ class TestViewMethodsMixin(unittest.TestCase): @reify def response(self): return DummyResponse() + request = Request(environ) request.registry = self.config.registry return request @@ -810,6 +985,7 @@ class TestViewMethodsMixin(unittest.TestCase): self.assertTrue(exc is dummy_exc) self.assertTrue(request.exception is dummy_exc) return DummyResponse(b'foo') + self.config.add_view(exc_view, context=RuntimeError) request = self._makeOne() dummy_exc = RuntimeError() @@ -818,7 +994,7 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: response = request.invoke_exception_view() self.assertEqual(response.app_iter, [b'foo']) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_hides_attrs(self): @@ -829,6 +1005,7 @@ class TestViewMethodsMixin(unittest.TestCase): self.assertTrue(request.response is not orig_response) request.response.app_iter = [b'bar'] return request.response + self.config.add_view(exc_view, context=RuntimeError) request = self._makeOne() orig_exc = request.exception = DummyContext() @@ -842,15 +1019,17 @@ class TestViewMethodsMixin(unittest.TestCase): self.assertTrue(request.exception is ex) self.assertTrue(request.exc_info[1] is ex) self.assertTrue(request.response is orig_response) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_supports_alternate_requests(self): def exc_view(exc, request): self.assertTrue(request is other_req) from pyramid.threadlocal import get_current_request + self.assertTrue(get_current_request() is other_req) return DummyResponse(b'foo') + self.config.add_view(exc_view, context=RuntimeError) request = self._makeOne() other_req = self._makeOne() @@ -859,12 +1038,13 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: response = request.invoke_exception_view(request=other_req) self.assertEqual(response.app_iter, [b'foo']) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_supports_threadlocal_registry(self): def exc_view(exc, request): return DummyResponse(b'foo') + self.config.add_view(exc_view, context=RuntimeError) request = self._makeOne() del request.registry @@ -873,13 +1053,14 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: response = request.invoke_exception_view() self.assertEqual(response.app_iter, [b'foo']) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_raises_if_no_registry(self): request = self._makeOne() del request.registry from pyramid.threadlocal import manager + manager.push({'registry': None, 'request': request}) try: raise RuntimeError @@ -888,7 +1069,7 @@ class TestViewMethodsMixin(unittest.TestCase): request.invoke_exception_view() except RuntimeError as e: self.assertEqual(e.args[0], "Unable to retrieve registry") - else: # pragma: no cover + else: # pragma: no cover self.fail() finally: manager.pop() @@ -897,6 +1078,7 @@ class TestViewMethodsMixin(unittest.TestCase): def exc_view(exc, request): self.assertTrue(request.exc_info is exc_info) return DummyResponse(b'foo') + self.config.add_view(exc_view, context=RuntimeError) request = self._makeOne() try: @@ -908,7 +1090,10 @@ class TestViewMethodsMixin(unittest.TestCase): def test_it_rejects_secured_view(self): from pyramid.exceptions import Forbidden - def exc_view(exc, request): pass + + def exc_view(exc, request): + pass + self.config.testing_securitypolicy(permissive=False) self.config.add_view(exc_view, context=RuntimeError, permission='view') request = self._makeOne() @@ -916,12 +1101,13 @@ class TestViewMethodsMixin(unittest.TestCase): raise RuntimeError except RuntimeError: self.assertRaises(Forbidden, request.invoke_exception_view) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_allows_secured_view(self): def exc_view(exc, request): return DummyResponse(b'foo') + self.config.testing_securitypolicy(permissive=False) self.config.add_view(exc_view, context=RuntimeError, permission='view') request = self._makeOne() @@ -930,18 +1116,19 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: response = request.invoke_exception_view(secure=False) self.assertEqual(response.app_iter, [b'foo']) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_raises_if_not_found(self): from pyramid.httpexceptions import HTTPNotFound + request = self._makeOne() dummy_exc = RuntimeError() try: raise dummy_exc except RuntimeError: self.assertRaises(HTTPNotFound, request.invoke_exception_view) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_reraises_if_not_found(self): @@ -952,14 +1139,20 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: self.assertRaises( RuntimeError, - lambda: request.invoke_exception_view(reraise=True)) - else: # pragma: no cover + lambda: request.invoke_exception_view(reraise=True), + ) + else: # pragma: no cover self.fail() def test_it_raises_predicate_mismatch(self): from pyramid.exceptions import PredicateMismatch - def exc_view(exc, request): pass - self.config.add_view(exc_view, context=Exception, request_method='POST') + + def exc_view(exc, request): + pass + + self.config.add_view( + exc_view, context=Exception, request_method='POST' + ) request = self._makeOne() request.method = 'GET' dummy_exc = RuntimeError() @@ -967,12 +1160,16 @@ class TestViewMethodsMixin(unittest.TestCase): raise dummy_exc except RuntimeError: self.assertRaises(PredicateMismatch, request.invoke_exception_view) - else: # pragma: no cover + else: # pragma: no cover self.fail() def test_it_reraises_after_predicate_mismatch(self): - def exc_view(exc, request): pass - self.config.add_view(exc_view, context=Exception, request_method='POST') + def exc_view(exc, request): + pass + + self.config.add_view( + exc_view, context=Exception, request_method='POST' + ) request = self._makeOne() request.method = 'GET' dummy_exc = RuntimeError() @@ -981,23 +1178,29 @@ class TestViewMethodsMixin(unittest.TestCase): except RuntimeError: self.assertRaises( RuntimeError, - lambda: request.invoke_exception_view(reraise=True)) - else: # pragma: no cover + lambda: request.invoke_exception_view(reraise=True), + ) + else: # pragma: no cover self.fail() + class ExceptionResponse(Exception): status = '404 Not Found' app_iter = ['Not Found'] headerlist = [] + class DummyContext: pass + def make_view(response): def view(context, request): return response + return view + class DummyRequest: exception = None request_iface = IRequest @@ -1006,30 +1209,38 @@ class DummyRequest: if environ is None: environ = {} self.environ = environ - + + from pyramid.interfaces import IResponse + @implementer(IResponse) class DummyResponse(object): headerlist = () app_iter = () status = '200 OK' environ = None + def __init__(self, body=None): if body is None: self.app_iter = () else: self.app_iter = [body] + from zope.interface import Interface + + class IContext(Interface): pass + class DummyVenusianInfo(object): scope = 'notaclass' module = sys.modules['tests'] codeinfo = 'codeinfo' + class DummyVenusian(object): def __init__(self, info=None): if info is None: @@ -1041,9 +1252,11 @@ class DummyVenusian(object): self.attachments.append((wrapped, callback, category, depth)) return self.info + class DummyRegistry(object): pass + class DummyConfig(object): def __init__(self): self.settings = [] @@ -1058,14 +1271,15 @@ class DummyConfig(object): self.pkg = pkg return self + class DummyVenusianContext(object): def __init__(self): self.config = DummyConfig() - + + def call_venusian(venusian, context=None): if context is None: context = DummyVenusianContext() for wrapped, callback, category, depth in venusian.attachments: callback(context, None, None) return context.config - diff --git a/tests/test_viewderivers.py b/tests/test_viewderivers.py index 69dcc7d08..4ce0b8a9e 100644 --- a/tests/test_viewderivers.py +++ b/tests/test_viewderivers.py @@ -3,13 +3,10 @@ from zope.interface import implementer from pyramid import testing from pyramid.exceptions import ConfigurationError -from pyramid.interfaces import ( - IResponse, - IRequest, - ) +from pyramid.interfaces import IResponse, IRequest -class TestDeriveView(unittest.TestCase): +class TestDeriveView(unittest.TestCase): def setUp(self): self.config = testing.setUp() self.config.set_default_csrf_options(require_csrf=False) @@ -25,6 +22,7 @@ class TestDeriveView(unittest.TestCase): def _registerLogger(self): from pyramid.interfaces import IDebugLogger + logger = DummyLogger() self.config.registry.registerUtility(logger, IDebugLogger) return logger @@ -32,6 +30,7 @@ class TestDeriveView(unittest.TestCase): def _registerSecurityPolicy(self, permissive): from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy + policy = DummySecurityPolicy(permissive) self.config.registry.registerUtility(policy, IAuthenticationPolicy) self.config.registry.registerUtility(policy, IAuthorizationPolicy) @@ -39,6 +38,7 @@ class TestDeriveView(unittest.TestCase): def test_function_returns_non_adaptable(self): def view(request): return None + result = self.config.derive_view(view) self.assertFalse(result is view) try: @@ -49,14 +49,15 @@ class TestDeriveView(unittest.TestCase): 'Could not convert return value of the view callable function ' 'tests.test_viewderivers.view into a response ' 'object. The value returned was None. You may have forgotten ' - 'to return a value from the view callable.' - ) - else: # pragma: no cover + 'to return a value from the view callable.', + ) + else: # pragma: no cover raise AssertionError def test_function_returns_non_adaptable_dict(self): def view(request): - return {'a':1} + return {'a': 1} + result = self.config.derive_view(view) self.assertFalse(result is view) try: @@ -67,15 +68,16 @@ class TestDeriveView(unittest.TestCase): "Could not convert return value of the view callable function " "tests.test_viewderivers.view into a response " "object. The value returned was {'a': 1}. You may have " - "forgotten to define a renderer in the view configuration." - ) - else: # pragma: no cover + "forgotten to define a renderer in the view configuration.", + ) + else: # pragma: no cover raise AssertionError def test_instance_returns_non_adaptable(self): class AView(object): def __call__(self, request): return None + view = AView() result = self.config.derive_view(view) self.assertFalse(result is view) @@ -83,20 +85,29 @@ class TestDeriveView(unittest.TestCase): result(None, None) except ValueError as e: msg = e.args[0] - self.assertTrue(msg.startswith( - 'Could not convert return value of the view callable object ' - '<tests.test_viewderivers.')) - self.assertTrue(msg.endswith( - '> into a response object. The value returned was None. You ' - 'may have forgotten to return a value from the view callable.')) - else: # pragma: no cover + self.assertTrue( + msg.startswith( + 'Could not convert return value of the view callable object ' + '<tests.test_viewderivers.' + ) + ) + self.assertTrue( + msg.endswith( + '> into a response object. The value returned was None. You ' + 'may have forgotten to return a value from the view callable.' + ) + ) + else: # pragma: no cover raise AssertionError def test_function_returns_true_Response_no_renderer(self): from pyramid.response import Response + r = Response('Hello') + def view(request): return r + result = self.config.derive_view(view) self.assertFalse(result is view) response = result(None, None) @@ -104,9 +115,12 @@ class TestDeriveView(unittest.TestCase): def test_function_returns_true_Response_with_renderer(self): from pyramid.response import Response + r = Response('Hello') + def view(request): return r + renderer = object() result = self.config.derive_view(view) self.assertFalse(result is view) @@ -115,11 +129,14 @@ class TestDeriveView(unittest.TestCase): def test_requestonly_default_method_returns_non_adaptable(self): request = DummyRequest() + class AView(object): def __init__(self, request): pass + def __call__(self): return None + result = self.config.derive_view(AView) self.assertFalse(result is AView) try: @@ -131,18 +148,21 @@ class TestDeriveView(unittest.TestCase): 'method __call__ of ' 'class tests.test_viewderivers.AView into a ' 'response object. The value returned was None. You may have ' - 'forgotten to return a value from the view callable.' - ) - else: # pragma: no cover + 'forgotten to return a value from the view callable.', + ) + else: # pragma: no cover raise AssertionError def test_requestonly_nondefault_method_returns_non_adaptable(self): request = DummyRequest() + class AView(object): def __init__(self, request): pass + def theviewmethod(self): return None + result = self.config.derive_view(AView, attr='theviewmethod') self.assertFalse(result is AView) try: @@ -154,21 +174,24 @@ class TestDeriveView(unittest.TestCase): 'method theviewmethod of ' 'class tests.test_viewderivers.AView into a ' 'response object. The value returned was None. You may have ' - 'forgotten to return a value from the view callable.' - ) - else: # pragma: no cover + 'forgotten to return a value from the view callable.', + ) + else: # pragma: no cover raise AssertionError def test_requestonly_function(self): response = DummyResponse() + def view(request): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(result(None, None), response) def test_requestonly_function_with_renderer(self): response = DummyResponse() + class moo(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) @@ -176,10 +199,13 @@ class TestDeriveView(unittest.TestCase): self.assertEqual(view_inst, view) self.assertEqual(ctx, context) return response + def clone(self): return self + def view(request): return 'OK' + result = self.config.derive_view(view, renderer=moo()) self.assertFalse(result.__wraps__ is view) request = self._makeRequest() @@ -193,9 +219,12 @@ class TestDeriveView(unittest.TestCase): self.assertEqual(system['request'], request) self.assertEqual(system['context'], context) return b'moo' + return inner + def view(request): return 'OK' + self.config.add_renderer('moo', moo) result = self.config.derive_view(view, renderer='string') self.assertFalse(result is view) @@ -206,6 +235,7 @@ class TestDeriveView(unittest.TestCase): def test_requestonly_function_with_renderer_request_has_view(self): response = DummyResponse() + class moo(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) @@ -213,10 +243,13 @@ class TestDeriveView(unittest.TestCase): self.assertEqual(view_inst, 'view') self.assertEqual(ctx, context) return response + def clone(self): return self + def view(request): return 'OK' + result = self.config.derive_view(view, renderer=moo()) self.assertFalse(result.__wraps__ is view) request = self._makeRequest() @@ -228,11 +261,14 @@ class TestDeriveView(unittest.TestCase): def test_class_without_attr(self): response = DummyResponse() + class View(object): def __init__(self, request): pass + def __call__(self): return response + result = self.config.derive_view(View) request = self._makeRequest() self.assertEqual(result(None, request), response) @@ -240,11 +276,14 @@ class TestDeriveView(unittest.TestCase): def test_class_with_attr(self): response = DummyResponse() + class View(object): def __init__(self, request): pass + def another(self): return response + result = self.config.derive_view(View, attr='another') request = self._makeRequest() self.assertEqual(result(None, request), response) @@ -253,6 +292,7 @@ class TestDeriveView(unittest.TestCase): def test_as_function_context_and_request(self): def view(context, request): return 'OK' + result = self.config.derive_view(view) self.assertTrue(result.__wraps__ is view) self.assertFalse(hasattr(result, '__call_permissive__')) @@ -260,8 +300,10 @@ class TestDeriveView(unittest.TestCase): def test_as_function_requestonly(self): response = DummyResponse() + def view(request): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) @@ -272,11 +314,14 @@ class TestDeriveView(unittest.TestCase): def test_as_newstyle_class_context_and_request(self): response = DummyResponse() + class view(object): def __init__(self, context, request): pass + def __call__(self): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) @@ -289,11 +334,14 @@ class TestDeriveView(unittest.TestCase): def test_as_newstyle_class_requestonly(self): response = DummyResponse() + class view(object): def __init__(self, context, request): pass + def __call__(self): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) @@ -306,11 +354,14 @@ class TestDeriveView(unittest.TestCase): def test_as_oldstyle_class_context_and_request(self): response = DummyResponse() + class view: def __init__(self, context, request): pass + def __call__(self): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) @@ -323,11 +374,14 @@ class TestDeriveView(unittest.TestCase): def test_as_oldstyle_class_requestonly(self): response = DummyResponse() + class view: def __init__(self, context, request): pass + def __call__(self): return response + result = self.config.derive_view(view) self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) @@ -340,9 +394,11 @@ class TestDeriveView(unittest.TestCase): def test_as_instance_context_and_request(self): response = DummyResponse() + class View: def __call__(self, context, request): return response + view = View() result = self.config.derive_view(view) self.assertTrue(result.__wraps__ is view) @@ -351,9 +407,11 @@ class TestDeriveView(unittest.TestCase): def test_as_instance_requestonly(self): response = DummyResponse() + class View: def __call__(self, request): return response + view = View() result = self.config.derive_view(view) self.assertFalse(result is view) @@ -367,7 +425,8 @@ class TestDeriveView(unittest.TestCase): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() result = self.config._derive_view(view, permission='view') self.assertEqual(view.__module__, result.__module__) @@ -379,16 +438,19 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): Allowed " - "(no authorization policy in use)") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): Allowed " + "(no authorization policy in use)", + ) def test_with_debug_authorization_authn_policy_no_authz_policy(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict(debug_authorization=True) from pyramid.interfaces import IAuthenticationPolicy + policy = DummySecurityPolicy(False) self.config.registry.registerUtility(policy, IAuthenticationPolicy) logger = self._registerLogger() @@ -402,16 +464,19 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): Allowed " - "(no authorization policy in use)") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): Allowed " + "(no authorization policy in use)", + ) def test_with_debug_authorization_authz_policy_no_authn_policy(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict(debug_authorization=True) from pyramid.interfaces import IAuthorizationPolicy + policy = DummySecurityPolicy(False) self.config.registry.registerUtility(policy, IAuthorizationPolicy) logger = self._registerLogger() @@ -425,16 +490,19 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): Allowed " - "(no authorization policy in use)") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): Allowed " + "(no authorization policy in use)", + ) def test_with_debug_authorization_no_permission(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) self._registerSecurityPolicy(True) logger = self._registerLogger() result = self.config._derive_view(view) @@ -447,16 +515,19 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): Allowed (" - "no permission registered)") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): Allowed (" + "no permission registered)", + ) def test_debug_auth_permission_authpol_permitted(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() self._registerSecurityPolicy(True) result = self.config._derive_view(view, permission='view') @@ -469,15 +540,18 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): True") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): True", + ) def test_debug_auth_permission_authpol_permitted_no_request(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() self._registerSecurityPolicy(True) result = self.config._derive_view(view, permission='view') @@ -487,16 +561,20 @@ class TestDeriveView(unittest.TestCase): self.assertEqual(result.__call_permissive__.__wraps__, view) self.assertEqual(result(None, None), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url None (view name " - "None against context None): True") + self.assertEqual( + logger.messages[0], + "debug_authorization of url None (view name " + "None against context None): True", + ) def test_debug_auth_permission_authpol_denied(self): from pyramid.httpexceptions import HTTPForbidden + response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() self._registerSecurityPolicy(False) result = self.config._derive_view(view, permission='view') @@ -509,14 +587,17 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertRaises(HTTPForbidden, result, None, request) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): False") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): False", + ) def test_debug_auth_permission_authpol_denied2(self): view = lambda *arg: 'OK' self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) self._registerLogger() self._registerSecurityPolicy(False) result = self.config._derive_view(view, permission='view') @@ -531,13 +612,17 @@ class TestDeriveView(unittest.TestCase): def test_debug_auth_permission_authpol_overridden(self): from pyramid.security import NO_PERMISSION_REQUIRED + response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() self._registerSecurityPolicy(False) - result = self.config._derive_view(view, permission=NO_PERMISSION_REQUIRED) + result = self.config._derive_view( + view, permission=NO_PERMISSION_REQUIRED + ) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -547,20 +632,24 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context None): " - "Allowed (NO_PERMISSION_REQUIRED)") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context None): " + "Allowed (NO_PERMISSION_REQUIRED)", + ) def test_debug_auth_permission_authpol_permitted_excview(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = dict( - debug_authorization=True, reload_templates=True) + debug_authorization=True, reload_templates=True + ) logger = self._registerLogger() self._registerSecurityPolicy(True) result = self.config._derive_view( - view, context=Exception, permission='view') + view, context=Exception, permission='view' + ) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -570,15 +659,18 @@ class TestDeriveView(unittest.TestCase): request.url = 'url' self.assertEqual(result(Exception(), request), response) self.assertEqual(len(logger.messages), 1) - self.assertEqual(logger.messages[0], - "debug_authorization of url url (view name " - "'view_name' against context Exception()): True") + self.assertEqual( + logger.messages[0], + "debug_authorization of url url (view name " + "'view_name' against context Exception()): True", + ) def test_secured_view_authn_policy_no_authz_policy(self): response = DummyResponse() view = lambda *arg: response self.config.registry.settings = {} from pyramid.interfaces import IAuthenticationPolicy + policy = DummySecurityPolicy(False) self.config.registry.registerUtility(policy, IAuthenticationPolicy) result = self.config._derive_view(view, permission='view') @@ -596,6 +688,7 @@ class TestDeriveView(unittest.TestCase): view = lambda *arg: response self.config.registry.settings = {} from pyramid.interfaces import IAuthorizationPolicy + policy = DummySecurityPolicy(False) self.config.registry.registerUtility(policy, IAuthorizationPolicy) result = self.config._derive_view(view, permission='view') @@ -612,6 +705,7 @@ class TestDeriveView(unittest.TestCase): from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy from pyramid.httpexceptions import HTTPForbidden + response = DummyResponse() view = lambda *arg: response self.config.registry.settings = {} @@ -625,16 +719,20 @@ class TestDeriveView(unittest.TestCase): try: result(None, request) except HTTPForbidden as e: - self.assertEqual(e.message, - 'Unauthorized: <lambda> failed permission check') - else: # pragma: no cover + self.assertEqual( + e.message, 'Unauthorized: <lambda> failed permission check' + ) + else: # pragma: no cover raise AssertionError def test_secured_view_raises_forbidden_with_name(self): from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy from pyramid.httpexceptions import HTTPForbidden - def myview(request): pass + + def myview(request): + pass + self.config.registry.settings = {} policy = DummySecurityPolicy(False) self.config.registry.registerUtility(policy, IAuthenticationPolicy) @@ -646,22 +744,28 @@ class TestDeriveView(unittest.TestCase): try: result(None, request) except HTTPForbidden as e: - self.assertEqual(e.message, - 'Unauthorized: myview failed permission check') - else: # pragma: no cover + self.assertEqual( + e.message, 'Unauthorized: myview failed permission check' + ) + else: # pragma: no cover raise AssertionError def test_secured_view_skipped_by_default_on_exception_view(self): from pyramid.request import Request from pyramid.security import NO_PERMISSION_REQUIRED + def view(request): raise ValueError + def excview(request): return 'hello' + self._registerSecurityPolicy(False) self.config.add_settings({'debug_authorization': True}) self.config.set_default_permission('view') - self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED) + self.config.add_view( + view, name='foo', permission=NO_PERMISSION_REQUIRED + ) self.config.add_view(excview, context=ValueError, renderer='string') app = self.config.make_wsgi_app() request = Request.blank('/foo', base_url='http://example.com') @@ -673,13 +777,20 @@ class TestDeriveView(unittest.TestCase): from pyramid.httpexceptions import HTTPForbidden from pyramid.request import Request from pyramid.security import NO_PERMISSION_REQUIRED + def view(request): raise ValueError - def excview(request): pass + + def excview(request): + pass + self._registerSecurityPolicy(False) - self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED) - self.config.add_view(excview, context=ValueError, renderer='string', - permission='view') + self.config.add_view( + view, name='foo', permission=NO_PERMISSION_REQUIRED + ) + self.config.add_view( + excview, context=ValueError, renderer='string', permission='view' + ) app = self.config.make_wsgi_app() request = Request.blank('/foo', base_url='http://example.com') request.method = 'POST' @@ -687,20 +798,26 @@ class TestDeriveView(unittest.TestCase): request.get_response(app) except HTTPForbidden: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_secured_view_passed_on_explicit_exception_view(self): from pyramid.request import Request from pyramid.security import NO_PERMISSION_REQUIRED + def view(request): raise ValueError + def excview(request): return 'hello' + self._registerSecurityPolicy(True) - self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED) - self.config.add_view(excview, context=ValueError, renderer='string', - permission='view') + self.config.add_view( + view, name='foo', permission=NO_PERMISSION_REQUIRED + ) + self.config.add_view( + excview, context=ValueError, renderer='string', permission='view' + ) app = self.config.make_wsgi_app() request = Request.blank('/foo', base_url='http://example.com') request.method = 'POST' @@ -710,10 +827,13 @@ class TestDeriveView(unittest.TestCase): def test_predicate_mismatch_view_has_no_name(self): from pyramid.exceptions import PredicateMismatch + response = DummyResponse() view = lambda *arg: response + def predicate1(context, request): return False + predicate1.text = lambda *arg: 'text' result = self.config._derive_view(view, predicates=[predicate1]) request = self._makeRequest() @@ -721,16 +841,21 @@ class TestDeriveView(unittest.TestCase): try: result(None, None) except PredicateMismatch as e: - self.assertEqual(e.detail, - 'predicate mismatch for view <lambda> (text)') - else: # pragma: no cover + self.assertEqual( + e.detail, 'predicate mismatch for view <lambda> (text)' + ) + else: # pragma: no cover raise AssertionError def test_predicate_mismatch_view_has_name(self): from pyramid.exceptions import PredicateMismatch - def myview(request): pass + + def myview(request): + pass + def predicate1(context, request): return False + predicate1.text = lambda *arg: 'text' result = self.config._derive_view(myview, predicates=[predicate1]) request = self._makeRequest() @@ -738,44 +863,57 @@ class TestDeriveView(unittest.TestCase): try: result(None, None) except PredicateMismatch as e: - self.assertEqual(e.detail, - 'predicate mismatch for view myview (text)') - else: # pragma: no cover + self.assertEqual( + e.detail, 'predicate mismatch for view myview (text)' + ) + else: # pragma: no cover raise AssertionError def test_predicate_mismatch_exception_has_text_in_detail(self): from pyramid.exceptions import PredicateMismatch - def myview(request): pass + + def myview(request): + pass + def predicate1(context, request): return True + predicate1.text = lambda *arg: 'pred1' + def predicate2(context, request): return False + predicate2.text = lambda *arg: 'pred2' - result = self.config._derive_view(myview, - predicates=[predicate1, predicate2]) + result = self.config._derive_view( + myview, predicates=[predicate1, predicate2] + ) request = self._makeRequest() request.method = 'POST' try: result(None, None) except PredicateMismatch as e: - self.assertEqual(e.detail, - 'predicate mismatch for view myview (pred2)') - else: # pragma: no cover + self.assertEqual( + e.detail, 'predicate mismatch for view myview (pred2)' + ) + else: # pragma: no cover raise AssertionError def test_with_predicates_all(self): response = DummyResponse() view = lambda *arg: response predicates = [] + def predicate1(context, request): predicates.append(True) return True + def predicate2(context, request): predicates.append(True) return True - result = self.config._derive_view(view, - predicates=[predicate1, predicate2]) + + result = self.config._derive_view( + view, predicates=[predicate1, predicate2] + ) request = self._makeRequest() request.method = 'POST' next = result(None, None) @@ -785,14 +923,18 @@ class TestDeriveView(unittest.TestCase): def test_with_predicates_checker(self): view = lambda *arg: 'OK' predicates = [] + def predicate1(context, request): predicates.append(True) return True + def predicate2(context, request): predicates.append(True) return True - result = self.config._derive_view(view, - predicates=[predicate1, predicate2]) + + result = self.config._derive_view( + view, predicates=[predicate1, predicate2] + ) request = self._makeRequest() request.method = 'POST' next = result.__predicated__(None, None) @@ -801,18 +943,24 @@ class TestDeriveView(unittest.TestCase): def test_with_predicates_notall(self): from pyramid.httpexceptions import HTTPNotFound + view = lambda *arg: 'OK' predicates = [] + def predicate1(context, request): predicates.append(True) return True + predicate1.text = lambda *arg: 'text' + def predicate2(context, request): predicates.append(True) return False + predicate2.text = lambda *arg: 'text' - result = self.config._derive_view(view, - predicates=[predicate1, predicate2]) + result = self.config._derive_view( + view, predicates=[predicate1, predicate2] + ) request = self._makeRequest() request.method = 'POST' self.assertRaises(HTTPNotFound, result, None, None) @@ -822,19 +970,26 @@ class TestDeriveView(unittest.TestCase): from pyramid.response import Response from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier + inner_response = Response('OK') + def inner_view(context, request): return inner_response + def outer_view(context, request): self.assertEqual(request.wrapped_response, inner_response) self.assertEqual(request.wrapped_body, inner_response.body) - self.assertEqual(request.wrapped_view.__original_view__, - inner_view) + self.assertEqual( + request.wrapped_view.__original_view__, inner_view + ) return Response(b'outer ' + request.wrapped_body) + self.config.registry.registerAdapter( - outer_view, (IViewClassifier, None, None), IView, 'owrap') - result = self.config._derive_view(inner_view, viewname='inner', - wrapper_viewname='owrap') + outer_view, (IViewClassifier, None, None), IView, 'owrap' + ) + result = self.config._derive_view( + inner_view, viewname='inner', wrapper_viewname='owrap' + ) self.assertFalse(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) self.assertEqual(inner_view.__doc__, result.__doc__) @@ -844,32 +999,42 @@ class TestDeriveView(unittest.TestCase): def test_with_wrapper_viewname_notfound(self): from pyramid.response import Response + inner_response = Response('OK') + def inner_view(context, request): return inner_response - wrapped = self.config._derive_view(inner_view, viewname='inner', - wrapper_viewname='owrap') + + wrapped = self.config._derive_view( + inner_view, viewname='inner', wrapper_viewname='owrap' + ) request = self._makeRequest() self.assertRaises(ValueError, wrapped, None, request) def test_as_newstyle_class_context_and_request_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) return response + def clone(self): return self + class View(object): def __init__(self, context, request): pass + def index(self): - return {'a':'1'} - result = self.config._derive_view(View, - renderer=renderer(), attr='index') + return {'a': '1'} + + result = self.config._derive_view( + View, renderer=renderer(), attr='index' + ) self.assertFalse(result is View) self.assertEqual(result.__module__, View.__module__) self.assertEqual(result.__doc__, View.__doc__) @@ -880,22 +1045,28 @@ class TestDeriveView(unittest.TestCase): def test_as_newstyle_class_requestonly_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) return response + def clone(self): return self + class View(object): def __init__(self, request): pass + def index(self): - return {'a':'1'} - result = self.config.derive_view(View, - renderer=renderer(), attr='index') + return {'a': '1'} + + result = self.config.derive_view( + View, renderer=renderer(), attr='index' + ) self.assertFalse(result is View) self.assertEqual(result.__module__, View.__module__) self.assertEqual(result.__doc__, View.__doc__) @@ -906,22 +1077,28 @@ class TestDeriveView(unittest.TestCase): def test_as_oldstyle_cls_context_request_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) return response + def clone(self): return self + class View: def __init__(self, context, request): pass + def index(self): - return {'a':'1'} - result = self.config.derive_view(View, - renderer=renderer(), attr='index') + return {'a': '1'} + + result = self.config.derive_view( + View, renderer=renderer(), attr='index' + ) self.assertFalse(result is View) self.assertEqual(result.__module__, View.__module__) self.assertEqual(result.__doc__, View.__doc__) @@ -932,22 +1109,28 @@ class TestDeriveView(unittest.TestCase): def test_as_oldstyle_cls_requestonly_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) return response + def clone(self): return self + class View: def __init__(self, request): pass + def index(self): - return {'a':'1'} - result = self.config.derive_view(View, - renderer=renderer(), attr='index') + return {'a': '1'} + + result = self.config.derive_view( + View, renderer=renderer(), attr='index' + ) self.assertFalse(result is View) self.assertEqual(result.__module__, View.__module__) self.assertEqual(result.__doc__, View.__doc__) @@ -958,21 +1141,26 @@ class TestDeriveView(unittest.TestCase): def test_as_instance_context_and_request_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst, view) self.assertEqual(ctx, context) return response + def clone(self): return self + class View: def index(self, context, request): - return {'a':'1'} + return {'a': '1'} + view = View() - result = self.config.derive_view(view, - renderer=renderer(), attr='index') + result = self.config.derive_view( + view, renderer=renderer(), attr='index' + ) self.assertFalse(result is view) self.assertEqual(result.__module__, view.__module__) self.assertEqual(result.__doc__, view.__doc__) @@ -982,21 +1170,26 @@ class TestDeriveView(unittest.TestCase): def test_as_instance_requestonly_attr_and_renderer(self): response = DummyResponse() + class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) - self.assertEqual(resp, {'a':'1'}) + self.assertEqual(resp, {'a': '1'}) self.assertEqual(view_inst, view) self.assertEqual(ctx, context) return response + def clone(self): return self + class View: def index(self, request): - return {'a':'1'} + return {'a': '1'} + view = View() - result = self.config.derive_view(view, - renderer=renderer(), attr='index') + result = self.config.derive_view( + view, renderer=renderer(), attr='index' + ) self.assertFalse(result is view) self.assertEqual(result.__module__, view.__module__) self.assertEqual(result.__doc__, view.__doc__) @@ -1006,29 +1199,42 @@ class TestDeriveView(unittest.TestCase): def test_with_view_mapper_config_specified(self): response = DummyResponse() + class mapper(object): def __init__(self, **kw): self.kw = kw + def __call__(self, view): def wrapped(context, request): return response + return wrapped - def view(context, request): return 'NOTOK' + + def view(context, request): + return 'NOTOK' + result = self.config._derive_view(view, mapper=mapper) self.assertFalse(result.__wraps__ is view) self.assertEqual(result(None, None), response) def test_with_view_mapper_view_specified(self): from pyramid.response import Response + response = Response() + def mapper(**kw): def inner(view): def superinner(context, request): self.assertEqual(request, None) return response + return superinner + return inner - def view(context, request): return 'NOTOK' + + def view(context, request): + return 'NOTOK' + view.__view_mapper__ = mapper result = self.config.derive_view(view) self.assertFalse(result.__wraps__ is view) @@ -1036,37 +1242,53 @@ class TestDeriveView(unittest.TestCase): def test_with_view_mapper_default_mapper_specified(self): from pyramid.response import Response + response = Response() + def mapper(**kw): def inner(view): def superinner(context, request): self.assertEqual(request, None) - return response + return response + return superinner + return inner + self.config.set_view_mapper(mapper) - def view(context, request): return 'NOTOK' + + def view(context, request): + return 'NOTOK' + result = self.config.derive_view(view) self.assertFalse(result.__wraps__ is view) self.assertEqual(result(None, None), response) def test_attr_wrapped_view_branching_default_phash(self): from pyramid.config.util import DEFAULT_PHASH - def view(context, request): pass + + def view(context, request): + pass + result = self.config._derive_view(view, phash=DEFAULT_PHASH) self.assertEqual(result.__wraps__, view) def test_attr_wrapped_view_branching_nondefault_phash(self): - def view(context, request): pass + def view(context, request): + pass + result = self.config._derive_view(view, phash='nondefault') self.assertNotEqual(result, view) def test_http_cached_view_integer(self): import datetime from pyramid.response import Response + response = Response('OK') + def inner_view(context, request): return response + result = self.config._derive_view(inner_view, http_cache=3600) self.assertFalse(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) @@ -1083,11 +1305,15 @@ class TestDeriveView(unittest.TestCase): def test_http_cached_view_timedelta(self): import datetime from pyramid.response import Response + response = Response('OK') + def inner_view(context, request): return response - result = self.config._derive_view(inner_view, - http_cache=datetime.timedelta(hours=1)) + + result = self.config._derive_view( + inner_view, http_cache=datetime.timedelta(hours=1) + ) self.assertFalse(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) self.assertEqual(inner_view.__doc__, result.__doc__) @@ -1103,11 +1329,15 @@ class TestDeriveView(unittest.TestCase): def test_http_cached_view_tuple(self): import datetime from pyramid.response import Response + response = Response('OK') + def inner_view(context, request): return response - result = self.config._derive_view(inner_view, - http_cache=(3600, {'public':True})) + + result = self.config._derive_view( + inner_view, http_cache=(3600, {'public': True}) + ) self.assertFalse(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) self.assertEqual(inner_view.__doc__, result.__doc__) @@ -1122,11 +1352,15 @@ class TestDeriveView(unittest.TestCase): def test_http_cached_view_tuple_seconds_None(self): from pyramid.response import Response + response = Response('OK') + def inner_view(context, request): return response - result = self.config._derive_view(inner_view, - http_cache=(None, {'public':True})) + + result = self.config._derive_view( + inner_view, http_cache=(None, {'public': True}) + ) self.assertFalse(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) self.assertEqual(inner_view.__doc__, result.__doc__) @@ -1139,14 +1373,17 @@ class TestDeriveView(unittest.TestCase): def test_http_cached_view_prevent_auto_set(self): from pyramid.response import Response + response = Response() response.cache_control.prevent_auto = True + def inner_view(context, request): return response + result = self.config._derive_view(inner_view, http_cache=3600) request = self._makeRequest() result = result(None, request) - self.assertEqual(result, response) # doesn't blow up + self.assertEqual(result, response) # doesn't blow up headers = dict(result.headerlist) self.assertFalse('Expires' in headers) self.assertFalse('Cache-Control' in headers) @@ -1154,9 +1391,12 @@ class TestDeriveView(unittest.TestCase): def test_http_cached_prevent_http_cache_in_settings(self): self.config.registry.settings['prevent_http_cache'] = True from pyramid.response import Response + response = Response() + def inner_view(context, request): return response + result = self.config._derive_view(inner_view, http_cache=3600) request = self._makeRequest() result = result(None, request) @@ -1166,14 +1406,22 @@ class TestDeriveView(unittest.TestCase): self.assertFalse('Cache-Control' in headers) def test_http_cached_view_bad_tuple(self): - def view(request): pass - self.assertRaises(ConfigurationError, self.config._derive_view, - view, http_cache=(None,)) + def view(request): + pass + + self.assertRaises( + ConfigurationError, + self.config._derive_view, + view, + http_cache=(None,), + ) def test_csrf_view_ignores_GET(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.method = 'GET' view = self.config._derive_view(inner_view, require_csrf=True) @@ -1182,7 +1430,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_fails_with_bad_POST_header(self): from pyramid.exceptions import BadCSRFToken - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1193,8 +1444,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_passes_with_good_POST_header(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1206,7 +1459,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_fails_with_bad_POST_token(self): from pyramid.exceptions import BadCSRFToken - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1217,8 +1473,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_passes_with_good_POST_token(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1230,8 +1488,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_https_domain(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "https" request.domain = "example.com" @@ -1246,7 +1506,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_fails_on_bad_PUT_header(self): from pyramid.exceptions import BadCSRFToken - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.scheme = "http" request.method = 'PUT' @@ -1257,7 +1520,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_fails_on_bad_referrer(self): from pyramid.exceptions import BadCSRFOrigin - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.method = "POST" request.scheme = "https" @@ -1270,7 +1536,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_fails_on_bad_origin(self): from pyramid.exceptions import BadCSRFOrigin - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.method = "POST" request.scheme = "https" @@ -1283,7 +1552,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_enabled_by_default(self): from pyramid.exceptions import BadCSRFToken - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1295,35 +1567,48 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_enabled_via_callback(self): def callback(request): return True + from pyramid.exceptions import BadCSRFToken - def inner_view(request): pass + + def inner_view(request): + pass + request = self._makeRequest() request.scheme = "http" request.method = 'POST' request.session = DummySession({'csrf_token': 'foo'}) - self.config.set_default_csrf_options(require_csrf=True, callback=callback) + self.config.set_default_csrf_options( + require_csrf=True, callback=callback + ) view = self.config._derive_view(inner_view) self.assertRaises(BadCSRFToken, lambda: view(None, request)) def test_csrf_view_disabled_via_callback(self): def callback(request): return False + response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' request.session = DummySession({'csrf_token': 'foo'}) - self.config.set_default_csrf_options(require_csrf=True, callback=callback) + self.config.set_default_csrf_options( + require_csrf=True, callback=callback + ) view = self.config._derive_view(inner_view) result = view(None, request) self.assertTrue(result is response) def test_csrf_view_uses_custom_csrf_token(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1336,8 +1621,10 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_uses_custom_csrf_header(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1350,22 +1637,27 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_uses_custom_methods(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'PUT' request.session = DummySession({'csrf_token': 'foo'}) self.config.set_default_csrf_options( - require_csrf=True, safe_methods=['PUT']) + require_csrf=True, safe_methods=['PUT'] + ) view = self.config._derive_view(inner_view) result = view(None, request) self.assertTrue(result is response) def test_csrf_view_uses_view_option_override(self): response = DummyResponse() + def inner_view(request): return response + request = self._makeRequest() request.scheme = "http" request.method = 'POST' @@ -1378,13 +1670,17 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_skipped_by_default_on_exception_view(self): from pyramid.request import Request + def view(request): raise ValueError + def excview(request): return 'hello' + self.config.set_default_csrf_options(require_csrf=True) self.config.set_session_factory( - lambda request: DummySession({'csrf_token': 'foo'})) + lambda request: DummySession({'csrf_token': 'foo'}) + ) self.config.add_view(view, name='foo', require_csrf=False) self.config.add_view(excview, context=ValueError, renderer='string') app = self.config.make_wsgi_app() @@ -1396,15 +1692,21 @@ class TestDeriveView(unittest.TestCase): def test_csrf_view_failed_on_explicit_exception_view(self): from pyramid.exceptions import BadCSRFToken from pyramid.request import Request + def view(request): raise ValueError - def excview(request): pass + + def excview(request): + pass + self.config.set_default_csrf_options(require_csrf=True) self.config.set_session_factory( - lambda request: DummySession({'csrf_token': 'foo'})) + lambda request: DummySession({'csrf_token': 'foo'}) + ) self.config.add_view(view, name='foo', require_csrf=False) - self.config.add_view(excview, context=ValueError, renderer='string', - require_csrf=True) + self.config.add_view( + excview, context=ValueError, renderer='string', require_csrf=True + ) app = self.config.make_wsgi_app() request = Request.blank('/foo', base_url='http://example.com') request.method = 'POST' @@ -1412,21 +1714,26 @@ class TestDeriveView(unittest.TestCase): request.get_response(app) except BadCSRFToken: pass - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_csrf_view_passed_on_explicit_exception_view(self): from pyramid.request import Request + def view(request): raise ValueError + def excview(request): return 'hello' + self.config.set_default_csrf_options(require_csrf=True) self.config.set_session_factory( - lambda request: DummySession({'csrf_token': 'foo'})) + lambda request: DummySession({'csrf_token': 'foo'}) + ) self.config.add_view(view, name='foo', require_csrf=False) - self.config.add_view(excview, context=ValueError, renderer='string', - require_csrf=True) + self.config.add_view( + excview, context=ValueError, renderer='string', require_csrf=True + ) app = self.config.make_wsgi_app() request = Request.blank('/foo', base_url='http://example.com') request.method = 'POST' @@ -1447,24 +1754,29 @@ class TestDerivationOrder(unittest.TestCase): from pyramid.interfaces import IViewDerivers self.config.add_view_deriver(None, 'deriv1') - self.config.add_view_deriver(None, 'deriv2', 'decorated_view', 'deriv1') + self.config.add_view_deriver( + None, 'deriv2', 'decorated_view', 'deriv1' + ) self.config.add_view_deriver(None, 'deriv3', 'deriv2', 'deriv1') derivers = self.config.registry.getUtility(IViewDerivers) derivers_sorted = derivers.sorted() dlist = [d for (d, _) in derivers_sorted] - self.assertEqual([ - 'secured_view', - 'csrf_view', - 'owrapped_view', - 'http_cached_view', - 'decorated_view', - 'deriv2', - 'deriv3', - 'deriv1', - 'rendered_view', - 'mapped_view', - ], dlist) + self.assertEqual( + [ + 'secured_view', + 'csrf_view', + 'owrapped_view', + 'http_cached_view', + 'decorated_view', + 'deriv2', + 'deriv3', + 'deriv1', + 'rendered_view', + 'mapped_view', + ], + dlist, + ) def test_right_order_implicit(self): from pyramid.interfaces import IViewDerivers @@ -1476,65 +1788,76 @@ class TestDerivationOrder(unittest.TestCase): derivers = self.config.registry.getUtility(IViewDerivers) derivers_sorted = derivers.sorted() dlist = [d for (d, _) in derivers_sorted] - self.assertEqual([ - 'secured_view', - 'csrf_view', - 'owrapped_view', - 'http_cached_view', - 'decorated_view', - 'deriv3', - 'deriv2', - 'deriv1', - 'rendered_view', - 'mapped_view', - ], dlist) + self.assertEqual( + [ + 'secured_view', + 'csrf_view', + 'owrapped_view', + 'http_cached_view', + 'decorated_view', + 'deriv3', + 'deriv2', + 'deriv1', + 'rendered_view', + 'mapped_view', + ], + dlist, + ) def test_right_order_under_rendered_view(self): from pyramid.interfaces import IViewDerivers - self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view') + self.config.add_view_deriver( + None, 'deriv1', 'rendered_view', 'mapped_view' + ) derivers = self.config.registry.getUtility(IViewDerivers) derivers_sorted = derivers.sorted() dlist = [d for (d, _) in derivers_sorted] - self.assertEqual([ - 'secured_view', - 'csrf_view', - 'owrapped_view', - 'http_cached_view', - 'decorated_view', - 'rendered_view', - 'deriv1', - 'mapped_view', - ], dlist) - + self.assertEqual( + [ + 'secured_view', + 'csrf_view', + 'owrapped_view', + 'http_cached_view', + 'decorated_view', + 'rendered_view', + 'deriv1', + 'mapped_view', + ], + dlist, + ) def test_right_order_under_rendered_view_others(self): from pyramid.interfaces import IViewDerivers - self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view') + self.config.add_view_deriver( + None, 'deriv1', 'rendered_view', 'mapped_view' + ) self.config.add_view_deriver(None, 'deriv2') self.config.add_view_deriver(None, 'deriv3') derivers = self.config.registry.getUtility(IViewDerivers) derivers_sorted = derivers.sorted() dlist = [d for (d, _) in derivers_sorted] - self.assertEqual([ - 'secured_view', - 'csrf_view', - 'owrapped_view', - 'http_cached_view', - 'decorated_view', - 'deriv3', - 'deriv2', - 'rendered_view', - 'deriv1', - 'mapped_view', - ], dlist) + self.assertEqual( + [ + 'secured_view', + 'csrf_view', + 'owrapped_view', + 'http_cached_view', + 'decorated_view', + 'deriv3', + 'deriv2', + 'rendered_view', + 'deriv1', + 'mapped_view', + ], + dlist, + ) class TestAddDeriver(unittest.TestCase): - def setUp(self): self.config = testing.setUp() @@ -1589,6 +1912,7 @@ class TestAddDeriver(unittest.TestCase): def test_override_mapped_view(self): from pyramid.viewderivers import VIEW + response = DummyResponse() view = lambda *arg: response flags = {} @@ -1602,12 +1926,14 @@ class TestAddDeriver(unittest.TestCase): flags.clear() self.config.add_view_deriver( - deriv1, name='mapped_view', under='rendered_view', over=VIEW) + deriv1, name='mapped_view', under='rendered_view', over=VIEW + ) result = self.config._derive_view(view) self.assertTrue(flags.get('deriv1')) def test_add_multi_derivers_ordered(self): from pyramid.viewderivers import INGRESS + response = DummyResponse() view = lambda *arg: response response.deriv = [] @@ -1632,7 +1958,10 @@ class TestAddDeriver(unittest.TestCase): def test_add_deriver_without_name(self): from pyramid.interfaces import IViewDerivers - def deriv1(view, info): pass + + def deriv1(view, info): + pass + self.config.add_view_deriver(deriv1) derivers = self.config.registry.getUtility(IViewDerivers) self.assertTrue('deriv1' in derivers.names) @@ -1640,40 +1969,53 @@ class TestAddDeriver(unittest.TestCase): def test_add_deriver_reserves_ingress(self): from pyramid.exceptions import ConfigurationError from pyramid.viewderivers import INGRESS - def deriv1(view, info): pass + + def deriv1(view, info): + pass + self.assertRaises( - ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS) + ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS + ) def test_add_deriver_enforces_ingress_is_first(self): from pyramid.exceptions import ConfigurationError from pyramid.viewderivers import INGRESS - def deriv1(view, info): pass + + def deriv1(view, info): + pass + try: self.config.add_view_deriver(deriv1, over=INGRESS) except ConfigurationError as ex: self.assertTrue('cannot be over INGRESS' in ex.args[0]) - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_add_deriver_enforces_view_is_last(self): from pyramid.exceptions import ConfigurationError from pyramid.viewderivers import VIEW - def deriv1(view, info): pass + + def deriv1(view, info): + pass + try: self.config.add_view_deriver(deriv1, under=VIEW) except ConfigurationError as ex: self.assertTrue('cannot be under VIEW' in ex.args[0]) - else: # pragma: no cover + else: # pragma: no cover raise AssertionError def test_add_deriver_enforces_mapped_view_is_last(self): from pyramid.exceptions import ConfigurationError - def deriv1(view, info): pass + + def deriv1(view, info): + pass + try: self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view') except ConfigurationError as ex: self.assertTrue('cannot be under "mapped_view"' in ex.args[0]) - else: # pragma: no cover + else: # pragma: no cover raise AssertionError @@ -1685,20 +2027,25 @@ class TestDeriverIntegration(unittest.TestCase): self.config = None testing.tearDown() - def _getViewCallable(self, config, ctx_iface=None, request_iface=None, - name=''): + def _getViewCallable( + self, config, ctx_iface=None, request_iface=None, name='' + ): from zope.interface import Interface from pyramid.interfaces import IRequest from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier + classifier = IViewClassifier if ctx_iface is None: ctx_iface = Interface if request_iface is None: request_iface = IRequest return config.registry.adapters.lookup( - (classifier, request_iface, ctx_iface), IView, name=name, - default=None) + (classifier, request_iface, ctx_iface), + IView, + name=name, + default=None, + ) def _makeRequest(self, config): request = DummyRequest() @@ -1713,11 +2060,13 @@ class TestDeriverIntegration(unittest.TestCase): def deriv1(view, info): response.deriv.append(info.options['deriv1']) return view + deriv1.options = ('deriv1',) def deriv2(view, info): response.deriv.append(info.options['deriv2']) return view + deriv2.options = ('deriv2',) self.config.add_view_deriver(deriv1, 'deriv1') @@ -1732,11 +2081,16 @@ class TestDeriverIntegration(unittest.TestCase): def test_unexpected_view_options(self): from pyramid.exceptions import ConfigurationError - def deriv1(view, info): pass + + def deriv1(view, info): + pass + self.config.add_view_deriver(deriv1, 'deriv1') self.assertRaises( ConfigurationError, - lambda: self.config.add_view(lambda r: {}, deriv1='test1')) + lambda: self.config.add_view(lambda r: {}, deriv1='test1'), + ) + @implementer(IResponse) class DummyResponse(object): @@ -1744,10 +2098,11 @@ class DummyResponse(object): default_content_type = None body = None + class DummyRequest: subpath = () matchdict = None - request_iface = IRequest + request_iface = IRequest def __init__(self, environ=None): if environ is None: @@ -1759,14 +2114,18 @@ class DummyRequest: self.headers = {} self.response = DummyResponse() + class DummyLogger: def __init__(self): self.messages = [] + def info(self, msg): self.messages.append(msg) + warn = info debug = info + class DummySecurityPolicy: def __init__(self, permitted=True): self.permitted = permitted @@ -1777,19 +2136,23 @@ class DummySecurityPolicy: def permits(self, context, principals, permission): return self.permitted + class DummySession(dict): def get_csrf_token(self): return self['csrf_token'] + def parse_httpdate(s): import datetime + # cannot use %Z, must use literal GMT; Jython honors timezone # but CPython does not return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT") + def assert_similar_datetime(one, two): for attr in ('year', 'month', 'day', 'hour', 'minute'): one_attr = getattr(one, attr) two_attr = getattr(two, attr) - if not one_attr == two_attr: # pragma: no cover + if not one_attr == two_attr: # pragma: no cover raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr)) diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py index 4ddbc9201..a5a955621 100644 --- a/tests/test_wsgi.py +++ b/tests/test_wsgi.py @@ -1,8 +1,10 @@ import unittest + class WSGIAppTests(unittest.TestCase): def _callFUT(self, app): from pyramid.wsgi import wsgiapp + return wsgiapp(app) def test_wsgiapp_none(self): @@ -23,9 +25,11 @@ class WSGIAppTests(unittest.TestCase): response = decorator(context, request) self.assertEqual(response, app) + class WSGIApp2Tests(unittest.TestCase): def _callFUT(self, app): from pyramid.wsgi import wsgiapp2 + return wsgiapp2(app) def test_wsgiapp2_none(self): @@ -35,8 +39,10 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = ('subpath',) - request.environ = {'SCRIPT_NAME':'/foo', - 'PATH_INFO':'/b/view_name/subpath'} + request.environ = { + 'SCRIPT_NAME': '/foo', + 'PATH_INFO': '/b/view_name/subpath', + } decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -47,7 +53,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = ('subpath',) - request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/subpath'} + request.environ = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/b/subpath'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -58,7 +64,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = () - request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/view_name'} + request.environ = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/b/view_name'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -69,7 +75,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = () - request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/view_name'} + request.environ = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/view_name'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -80,7 +86,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = () - request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/'} + request.environ = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -91,7 +97,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = () - request.environ = {'SCRIPT_NAME':'', 'PATH_INFO':'/'} + request.environ = {'SCRIPT_NAME': '', 'PATH_INFO': '/'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -102,7 +108,7 @@ class WSGIApp2Tests(unittest.TestCase): context = DummyContext() request = DummyRequest() request.subpath = () - request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/'} + request.environ = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/'} app = DummyApp() decorator = self._callFUT(app) response = decorator(context, request) @@ -110,16 +116,20 @@ class WSGIApp2Tests(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/') self.assertEqual(request.environ['SCRIPT_NAME'], '/foo') + def dummyapp(environ, start_response): """ """ + class DummyApp(object): def __call__(self, environ, start_response): """ """ + class DummyContext: pass + class DummyRequest: def get_response(self, application): return application @@ -127,4 +137,3 @@ class DummyRequest: def copy(self): self.copied = True return self - |
