diff options
| author | Michael Merickel <github@m.merickel.org> | 2018-10-15 09:56:42 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-15 09:56:42 -0500 |
| commit | bda1306749c62ef4f11cfe567ed7d56c8ad94240 (patch) | |
| tree | 304c696c105ca15bbe0f13d96c79524974de768b | |
| parent | 81576ee51564c49d5ff3c1c07f214f22a8438231 (diff) | |
| parent | a54bc1ccac17625991e26eb5d4577f893803c683 (diff) | |
| download | pyramid-bda1306749c62ef4f11cfe567ed7d56c8ad94240.tar.gz pyramid-bda1306749c62ef4f11cfe567ed7d56c8ad94240.tar.bz2 pyramid-bda1306749c62ef4f11cfe567ed7d56c8ad94240.zip | |
Merge pull request #3388 from mmerickel/black
format source using black
183 files changed, 13558 insertions, 7217 deletions
diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..f8da47c1a --- /dev/null +++ b/.flake8 @@ -0,0 +1,18 @@ +[flake8] +ignore = + # E203: whitespace before ':' (black fails to be PEP8 compliant) + E203 + # E731: do not assign a lambda expression, use a def + E731 + # W503: line break before binary operator (flake8 is not PEP8 compliant) + W503 +exclude = + src/pyramid/compat.py + src/pyramid/scaffolds/alchemy + src/pyramid/scaffolds/starter + src/pyramid/scaffolds/zodb + tests/fixtures + tests/pkgs + tests/test_config/pkgs + tests/test_config/path +show-source = True diff --git a/.travis.yml b/.travis.yml index dcbd37294..6efbee21b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,11 @@ matrix: env: TOXENV=pypy - python: pypy3 env: TOXENV=pypy3 - - python: 3.5 + - python: 3.6 env: TOXENV=py2-cover,py3-cover,coverage - python: 3.5 env: TOXENV=docs - - python: 3.5 + - python: 3.6 env: TOXENV=lint - python: 3.7 env: TOXENV=py37 diff --git a/MANIFEST.in b/MANIFEST.in index 94da9d899..934fc973a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,7 +8,8 @@ include CHANGES.rst HISTORY.rst BFG_HISTORY.rst include CONTRIBUTORS.txt LICENSE.txt COPYRIGHT.txt include contributing.md RELEASING.txt -include .coveragerc tox.ini appveyor.yml .travis.yml rtd.txt +include .coveragerc .flake8 setup.cfg pyproject.toml +include tox.ini appveyor.yml .travis.yml rtd.txt graft .github include HACKING.txt hacking-tox.ini diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..b30e4f465 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,31 @@ +[build-system] +requires = ["setuptools", "wheel"] + +[tool.black] +line-length = 79 +skip-string-normalization = true +py36 = false +exclude = ''' +/( + \.git + | \.mypy_cache + | \.tox + | \.venv + | \.pytest_cache + | dist + | build + | docs + | src/pyramid/scaffolds/alchemy + | src/pyramid/scaffolds/starter + | src/pyramid/scaffolds/zodb +)/ +''' + + # This next section only exists for people that have their editors +# automatically call isort, black already sorts entries on its own when run. +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +combine_as_imports = true +line_length = 79 @@ -16,59 +16,6 @@ universal = 1 [metadata] license_file = LICENSE.txt -[flake8] -ignore = - # E121: continuation line under-indented for hanging indent - E121, - # E123: closing bracket does not match indentation of opening bracket's line - E123, - # E125: continuation line with same indent as next logical line - E125, - # E127: continuation line over-indented for visual indent - E127, - # E128: continuation line under-indented for visual indent - E128, - # E129: visually indented line with same indent as next logical line - E129, - # E201: whitespace after '(' - E201, - # E202: whitespace before ')' - E202, - # E231: missing whitespace after ',', ';', or ':' - E231, - # E261: at least two spaces before inline comment - E261, - # E262: inline comment should start with '# ' - E262, - # E265: block comment should start with '# ' - E265, - # E266: too many leading '#' for block comment - E266, - # E301: expected 1 blank line, found 0 - E301, - # E302: expected 2 blank lines, found 0 - E302, - # E303: too many blank lines (3) - E303, - # E305: expected 2 blank lines after class or function definition, found 1 - E305, - # E306: expected 1 blank line before a nested definition, found 0 - E306, - # E501: line too long (82 > 79 characters) - E501, - # E731: do not assign a lambda expression, use a def - E731, - # W291: trailing whitespace - W291, - # W293: blank line contains whitespace - W293, - # W391: blank line at end of file - W391, - # W503: line break before binary operator - W503 -exclude = pyramid/tests/,pyramid/compat.py,pyramid/resource.py -show-source = True - [check-manifest] ignore = .gitignore @@ -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..7cb6b6811 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 @@ -580,30 +596,31 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): .. versionchanged:: 1.10 Added the ``samesite`` option and made the default ``'Lax'``. - + Objects of this class implement the interface described by :class:`pyramid.interfaces.IAuthenticationPolicy`. """ - 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 @@ -986,8 +1044,9 @@ class AuthTktCookieHelper(object): "userid is of type {}, and is not supported by the " "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 + "string as the userid, it will not be decoded back to the " + "type 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 @@ -1094,8 +1154,8 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy): ``realm`` - Default: ``"Realm"``. The Basic Auth Realm string. Usually displayed to - the user by the browser in the login dialog. + Default: ``"Realm"``. The Basic Auth Realm string. Usually displayed + to the user by the browser in the login dialog. ``debug`` @@ -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..31832c874 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -7,8 +7,9 @@ WIN = platform.system() == 'Windows' try: # pragma: no cover import __pypy__ + PYPY = True -except: # pragma: no cover +except BaseException: # pragma: no cover __pypy__ = None PYPY = False @@ -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..f5790352e 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,12 +388,15 @@ 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: # # - the default exceptionresponse_view requires the superdefault view - # mapper, so we need to configure it before adding default_view_mapper + # mapper, so we need to configure it before adding + # default_view_mapper # # - superdefault renderers should be overrideable without requiring # the user to commit before calling config.add_renderer @@ -424,7 +411,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 +455,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 +467,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 +534,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 +543,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 +586,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 +630,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 +668,8 @@ class Configurator( info=action_info, includepath=self.includepath, introspectables=introspectables, - ) ) + ) self.action_state.action(**action) def _get_action_state(self): @@ -663,7 +686,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 +710,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 +823,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 +844,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 +910,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 +938,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 +964,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 +985,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 +1046,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 +1054,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 +1105,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 +1132,8 @@ class ActionState(object): info=info, order=order, introspectables=introspectables, - ) ) + ) self.actions.append(action) def execute_actions(self, clear=True, introspector=None): @@ -1179,8 +1215,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 +1238,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 +1327,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 +1388,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 +1402,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 +1433,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 +1453,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..4e1cb0762 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` @@ -158,8 +158,8 @@ class RoutesConfiguratorMixin(object): For backwards compatibility purposes (as of :app:`Pyramid` 1.0), a ``path`` keyword argument passed to this function will be used to represent the pattern value if the ``pattern`` argument is - ``None``. If both ``path`` and ``pattern`` are passed, ``pattern`` - wins. + ``None``. If both ``path`` and ``pattern`` are passed, + ``pattern`` wins. xhr @@ -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..b74a57adf 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): """ @@ -65,7 +56,7 @@ class TweensConfiguratorMixin(object): - An iterable of any combination of the above. This allows the user to specify fallbacks if the desired tween is not included, as well as compatibility with multiple other tweens. - + ``under`` means 'closer to the main Pyramid application than', ``over`` means 'closer to the request ingress than'. @@ -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..8723b7721 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 @@ -128,16 +126,13 @@ class PredicateList(object): def add(self, name, factory, weighs_more_than=None, weighs_less_than=None): # Predicates should be added to a predicate list in (presumed) # computation expense order. - ## if weighs_more_than is None and weighs_less_than is None: - ## weighs_more_than = self.last_added or FIRST - ## weighs_less_than = LAST + # if weighs_more_than is None and weighs_less_than is None: + # weighs_more_than = self.last_added or FIRST + # 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..cc5b48ecb 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* @@ -725,8 +728,8 @@ class ViewsConfiguratorMixin(object): If CSRF checking is performed, the checked value will be the value of ``request.params[check_name]``. This value will be compared against the value of ``policy.get_csrf_token()`` (where ``policy`` is an - implementation of :meth:`pyramid.interfaces.ICSRFStoragePolicy`), and the - check will pass if these two values are the same. If the check + implementation of :meth:`pyramid.interfaces.ICSRFStoragePolicy`), and + the check will pass if these two values are the same. If the check passes, the associated view will be permitted to execute. If the check fails, the associated view will not be permitted to execute. @@ -804,42 +807,49 @@ 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 +866,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 +889,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 +900,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 +941,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 +1032,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 +1105,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 +1129,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 +1156,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 +1191,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 +1210,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 +1222,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 +1247,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 +1266,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 +1282,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 +1311,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 +1349,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 +1413,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 +1439,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 +1456,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 +1476,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 +1568,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 +1615,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 +1658,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 +1692,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 +1730,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 +1759,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 @@ -1766,7 +1805,8 @@ class ViewsConfiguratorMixin(object): config.add_notfound_view(append_slash=HTTPMovedPermanently) The above means that a redirect to a slash-appended route will be - attempted, but instead of :class:`~pyramid.httpexceptions.HTTPTemporaryRedirect` + attempted, but instead of + :class:`~pyramid.httpexceptions.HTTPTemporaryRedirect` being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will be used` for the redirect response if a slash-appended route is found. @@ -1789,18 +1829,24 @@ class ViewsConfiguratorMixin(object): .. versionchanged: 1.10 - Default response was changed from :class:`~pyramid.httpexceptions.HTTPFound` + Default response was changed from + :class:`~pyramid.httpexceptions.HTTPFound` to :class:`~pyramid.httpexceptions.HTTPTemporaryRedirect`. """ 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 +1871,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 +1887,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 +1897,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 +1913,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 +1962,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 +2115,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 +2156,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 +2167,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 +2184,7 @@ class ViewDeriverInfo(object): def settings(self): return self.registry.settings + @implementer(IStaticURLInfo) class StaticURLInfo(object): def __init__(self): @@ -2134,12 +2194,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 +2208,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 +2225,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 +2253,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 +2272,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 +2298,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 +2309,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 +2346,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 +2381,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..fba5d9baa 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 @@ -246,8 +247,8 @@ def check_csrf_origin(request, trusted_origins=None, raises=True): Check the ``Origin`` of the request to see if it is a cross site request or not. - If the value supplied by the ``Origin`` or ``Referer`` header isn't one of the - trusted origins and ``raises`` is ``True``, this function will raise a + If the value supplied by the ``Origin`` or ``Referer`` header isn't one of + the trusted origins and ``raises`` is ``True``, this function will raise a :exc:`pyramid.exceptions.BadCSRFOrigin` exception, but if ``raises`` is ``False``, this function will return ``False`` instead. If the CSRF origin checks are successful this function will return ``True`` unconditionally. @@ -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..959a45f37 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,10 +155,10 @@ def _no_escape(value): value = text_type(value) return value + @implementer(IExceptionResponse) class HTTPException(Response, Exception): - - ## You should set in subclasses: + # You should set in subclasses: # code = 200 # title = 'OK' # explanation = 'why this happens' @@ -190,23 +186,29 @@ class HTTPException(Response, Exception): # implies that this class' ``exception`` property always returns # ``self`` (it exists only for bw compat at this point). # - # - documentation improvements (Pyramid-specific docstrings where necessary) + # - documentation improvements (Pyramid-specific docstrings where + # necessary) # 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 + # 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 +# 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) + +# FIXME: add 207 Multi-Status (but it's complicated) ############################################################ -## 3xx redirection +# 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 +# 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 + + # 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 + + # 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 + + # 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,13 +1162,14 @@ 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 +# 5xx Server Error ############################################################ # Response status codes beginning with the digit "5" indicate cases in # which the server is aware that it has erred or is incapable of @@ -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..e99a29aab 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 @@ -80,13 +82,13 @@ class Localizer(object): and ``plural`` objects should be unicode strings. There is no reason to use translation string objects as arguments as all metadata is ignored. - + ``n`` represents the number of elements. ``domain`` is the translation domain to use to do the pluralization, and ``mapping`` is the interpolation mapping that should be used on the result. If the ``domain`` is not supplied, a default domain is used (usually ``messages``). - + Example:: num = 1 @@ -108,12 +110,13 @@ class Localizer(object): num, mapping={'num':num}) - + """ 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): @@ -124,7 +127,7 @@ def default_locale_negotiator(request): the request object (possibly set by a view or a listener for an :term:`event`). If the attribute exists and it is not ``None``, its value will be used. - + - Then it looks for the ``request.params['_LOCALE_']`` value. - Then it looks for the ``request.cookies['_LOCALE_']`` value. @@ -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,9 +173,10 @@ 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 + corresponding to the provided locale name from the translations found in the list of translation directories.""" translations = Translations() translations._catalog = {} @@ -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 + """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..e2e211b67 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 @@ -1199,7 +1341,7 @@ class IIntrospectable(Interface): method = getattr(introspector, methodname) method((i.category_name, i.discriminator), (category_name, discriminator)) - """ + """ # noqa: E501 def __hash__(): @@ -1209,19 +1351,23 @@ 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') + action. The ParserInfo class used by ZCML implements the same interface. + """ + + 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 +1406,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 +1436,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 +1472,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 +1507,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..d90aed0d1 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 @@ -46,7 +48,7 @@ def lineage(resource): Calling ``lineage(thing2)`` will return a generator. When we turn it into a list, we will get:: - + list(lineage(thing2)) [ <Thing object at thing2>, <Thing object at thing1> ] """ @@ -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..22c09e41a 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 @@ -83,7 +87,7 @@ def bootstrap(config_uri, request=None, options=None): for you if none is provided. You can mutate the request's ``environ`` later to setup a specific host/port/scheme/etc. - ``options`` Is passed to get_app for use as variable assignments like + ``options`` Is passed to get_app for use as variable assignments like {'http_port': 8080} and then use %(http_port)s in the config file. @@ -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..8ddf4c447 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 -resolve_resource_spec = resolve_asset_spec -resource_spec_from_abspath = asset_spec_from_abspath -abspath_from_resource_spec = abspath_from_asset_spec +from pyramid.asset import * # noqa b/w compat + +resolve_resource_spec = resolve_asset_spec # noqa +resource_spec_from_abspath = asset_spec_from_abspath # noqa +abspath_from_resource_spec = abspath_from_asset_spec # noqa 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..eff71d204 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}) + """ # noqa: E501 + % {'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..2e3896976 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,94 +30,105 @@ 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` and returns its result. - + .. deprecated:: 1.5 Use :meth:`pyramid.request.Request.has_permission` instead. .. 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): """ A function that returns the value of the property :attr:`pyramid.request.Request.authenticated_userid`. - + .. 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): - """ + """ A function that returns the value of the property :attr:`pyramid.request.Request.unauthenticated_userid`. - + .. 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): """ A function that returns the value of the property :attr:`pyramid.request.Request.effective_principals`. - + .. 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..338b49083 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 @@ -360,21 +369,26 @@ def resource_path_tuple(resource, *elements): The :term:`root` resource *must* have a ``__name__`` attribute with a value of either ``None`` or the empty string for path tuples to be generated properly. If the root resource has a non-null ``__name__`` - attribute, its name will be the first element in the generated path tuple - rather than the empty string. + attribute, its name will be the first element in the generated path + tuple rather than the empty string. """ 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""" + """ Implementation detail shared by resource_path and + resource_path_tuple""" path = [loc.__name__ or '' for loc in lineage(resource)] path.reverse() 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 +426,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 +434,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 +450,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): @@ -501,19 +517,20 @@ def traversal_path_info(path): This function does not generate the same type of tuples that :func:`pyramid.traversal.resource_path_tuple` does. In particular, the - leading empty string is not present in the tuple it returns, unlike tuples - returned by :func:`pyramid.traversal.resource_path_tuple`. As a result, - tuples generated by ``traversal_path`` are not resolveable by the - :func:`pyramid.traversal.find_resource` API. ``traversal_path`` is a - function mostly used by the internals of :app:`Pyramid` and by people + leading empty string is not present in the tuple it returns, unlike + tuples returned by :func:`pyramid.traversal.resource_path_tuple`. As a + result, tuples generated by ``traversal_path`` are not resolveable by + the :func:`pyramid.traversal.find_resource` API. ``traversal_path`` is + a function mostly used by the internals of :app:`Pyramid` and by people writing their own traversal machinery, as opposed to users writing 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 +548,7 @@ def split_path_info(path): clean.append(segment) return tuple(clean) + _segment_cache = {} quote_path_segment_doc = """ \ @@ -574,7 +592,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 +602,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 +624,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 +635,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 +671,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 +691,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 +704,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 +785,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..00dd13bfe 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) @@ -181,10 +172,10 @@ class URLMethodsMixin(object): Python data structures that are passed as ``_query`` which are sequences or dictionaries are turned into a string under the same - rules as when run through :func:`urllib.urlencode` with the ``doseq`` - argument equal to ``True``. This means that sequences can be passed - as values, and a k=v pair will be placed into the query string for - each value. + rules as when run through :func:`urllib.urlencode` with the + ``doseq`` argument equal to ``True``. This means that sequences can + be passed as values, and a k=v pair will be placed into the query + string for each value. If a keyword argument ``_anchor`` is present, its string representation will be quoted per :rfc:`3986#section-3.5` and used as @@ -209,7 +200,7 @@ class URLMethodsMixin(object): ``_host='foo.com'``, and the URL that would have been generated without the host replacement is ``http://example.com/a``, the result will be ``http://foo.com/a``. - + Note that if ``_scheme`` is passed as ``https``, and ``_port`` is not passed, the ``_port`` value is assumed to have been passed as ``443``. Likewise, if ``_scheme`` is passed as ``http`` and @@ -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) @@ -372,10 +363,10 @@ class URLMethodsMixin(object): Python data structures that are passed as ``query`` which are sequences or dictionaries are turned into a string under the same - rules as when run through :func:`urllib.urlencode` with the ``doseq`` - argument equal to ``True``. This means that sequences can be passed - as values, and a k=v pair will be placed into the query string for - each value. + rules as when run through :func:`urllib.urlencode` with the + ``doseq`` argument equal to ``True``. This means that sequences can + be passed as values, and a k=v pair will be placed into the query + string for each value. If a keyword argument ``anchor`` is present, its string representation will be used as a named anchor in the generated URL @@ -399,7 +390,7 @@ class URLMethodsMixin(object): ``host='foo.com'``, and the URL that would have been generated without the host replacement is ``http://example.com/a``, the result will be ``http://foo.com/a``. - + If ``scheme`` is passed as ``https``, and an explicit ``port`` is not passed, the ``port`` value is assumed to have been passed as ``443``. Likewise, if ``scheme`` is passed as ``http`` and ``port`` is not @@ -424,11 +415,11 @@ class URLMethodsMixin(object): If the ``resource`` passed in has a ``__resource_url__`` method, it will be used to generate the URL (scheme, host, port, path) for the base resource which is operated upon by this function. - + .. seealso:: See also :ref:`overriding_resource_url_generation`. - + If ``route_name`` is passed, this function will delegate its URL production to the ``route_url`` function. Calling ``resource_url(someresource, 'element1', 'element2', query={'a':1}, @@ -481,21 +472,21 @@ class URLMethodsMixin(object): is passed, the ``__resource_url__`` method of the resource passed is ignored unconditionally. This feature is incompatible with resources which generate their own URLs. - + .. note:: - If the :term:`resource` used is the result of a :term:`traversal`, it - must be :term:`location`-aware. The resource can also be the context - of a :term:`URL dispatch`; contexts found this way do not need to be - location-aware. + If the :term:`resource` used is the result of a :term:`traversal`, + it must be :term:`location`-aware. The resource can also be the + context of a :term:`URL dispatch`; contexts found this way do not + need to be location-aware. .. note:: If a 'virtual root path' is present in the request environment (the value of the WSGI environ key ``HTTP_X_VHM_ROOT``), and the resource - was obtained via :term:`traversal`, the URL path will not include the - virtual root prefix (it will be stripped off the left hand side of - the generated URL). + was obtained via :term:`traversal`, the URL path will not include + the virtual root prefix (it will be stripped off the left hand side + of the generated URL). .. note:: @@ -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..9f58e72ae 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 @@ -201,19 +198,21 @@ class view_config(object): See the :py:func:`venusian.attach` function in Venusian for more information about the ``_depth`` and ``_category`` arguments. - + .. seealso:: - + See also :ref:`mapping_views_using_a_decorator_section` for details about using :class:`pyramid.view.view_config`. .. warning:: - + ``view_config`` will work ONLY on module top level members 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 @@ -392,7 +402,8 @@ class notfound_view_config(object): return HTTPNotFound('not found') The above means that a redirect to a slash-appended route will be - attempted, but instead of :class:`~pyramid.httpexceptions.HTTPTemporaryRedirect` + attempted, but instead of + :class:`~pyramid.httpexceptions.HTTPTemporaryRedirect` being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will be used` for the redirect response if a slash-appended route is found. @@ -417,8 +428,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 +439,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 +492,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 +503,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 +541,7 @@ class exception_view_config(object): Added the ``_depth`` and ``_category`` arguments. """ + venusian = venusian def __init__(self, *args, **settings): @@ -545,8 +561,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 +572,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 +583,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 +599,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 +615,7 @@ def _find_views( return views + def _call_view( registry, request, @@ -609,7 +626,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 +636,7 @@ def _call_view( view_name, view_types=view_types, view_classifier=view_classifier, - ) + ) pme = None response = None @@ -631,10 +648,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 +664,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 +755,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..fbe0c252c 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..fc42c317e 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): # pragma: no cover + 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..177f5637b 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 Exception: # 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..4a14caedf 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(): # pragma: no cover + return 'OK' self.assertFalse(is_unbound_method(func)) + class OldStyle: - def run(self): return 'OK' + def run(self): # pragma: no cover + return 'OK' + class NewStyle(object): - def run(self): return 'OK' + def run(self): # pragma: no cover + return 'OK' diff --git a/tests/test_config/__init__.py b/tests/test_config/__init__.py index 81d9f4965..ac1f19667 100644 --- a/tests/test_config/__init__.py +++ b/tests/test_config/__init__.py @@ -1,53 +1,70 @@ # package - +from functools import partial 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): # pragma: no cover + pass + + +def dummy_tween_factory2(handler, registry): # pragma: no cover + 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..d871e8825 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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..c03d3f68b 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): # pragma: no cover + 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): # pragma: no cover + pass + + def bar(self): # pragma: no cover + 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): # pragma: no cover + pass + config.add_request_method(name='foo') config.add_request_method(bar, name='foo') self.assertRaises(ConfigurationConflictError, config.commit) @@ -127,12 +161,13 @@ class TestFactoriesMixin(unittest.TestCase): self.assertRaises(AttributeError, config.add_request_method) def test_add_request_method_with_text_type_name(self): - from pyramid.interfaces import IRequestExtensions from pyramid.compat import text_, PY2 from pyramid.exceptions import ConfigurationError config = self._makeOne(autocommit=True) - def boomshaka(r): pass + + def boomshaka(r): # pragma: no cover + pass def get_bad_name(): if PY2: @@ -146,8 +181,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): # pragma: no cover + pass + config.set_execution_policy(dummy_policy) registry = config.registry result = registry.queryUtility(IExecutionPolicy) @@ -156,6 +195,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..b840c1976 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): # pragma: no cover + 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,91 @@ 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..2c92b60fb 100644 --- a/tests/test_config/test_init.py +++ b/tests/test_config/test_init.py @@ -1,6 +1,7 @@ -import unittest - import os +import unittest +from zope.interface import Interface +from zope.interface import implementer from pyramid.compat import im_func from pyramid.testing import skip_on @@ -17,20 +18,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 +49,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 +78,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 +89,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 +129,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 +143,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 +157,7 @@ class ConfiguratorTests(unittest.TestCase): def test_end(self): from pyramid.config import Configurator + config = Configurator() manager = DummyThreadLocalManager() pushed = manager.pushed @@ -143,14 +168,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 +187,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 +204,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 +219,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 +233,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 +241,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 +250,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 +288,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): # pragma: no cover + 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 +336,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 +380,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 +391,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 +433,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 +461,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 +499,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 +507,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 +537,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 +551,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 +585,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 +595,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 +606,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 +616,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 +628,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 +667,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 +677,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 +690,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 +704,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 +717,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 +730,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 +743,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 +757,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 +777,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 +790,12 @@ 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 +804,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 +835,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 +852,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 +865,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 +878,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 +891,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,41 +926,51 @@ 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) 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 +981,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 +999,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 +1033,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 +1062,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 +1074,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 +1098,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 +1115,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 +1155,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 +1188,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 +1204,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 +1231,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 +1293,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 +1308,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + 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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + def includeme(config): config.add_view(view2) + config.add_view(view1) config.include(includeme) config.commit() @@ -1165,12 +1339,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + def includeme1(config): config.add_view(view1) + def includeme2(config): config.add_view(view2) + config.include(includeme1) config.include(includeme2) try: @@ -1179,18 +1360,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + + def view3(request): # pragma: no cover + 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 +1390,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + + def view3(request): # pragma: no cover + pass + config.add_view(view1, renderer=null_renderer) config.add_view(view2, renderer=null_renderer) config.add_view(view3, renderer=null_renderer) @@ -1213,8 +1411,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + config.set_notfound_view(view1) config.set_notfound_view(view2) try: @@ -1223,13 +1426,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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + pass + config.set_forbidden_view(view1) config.set_forbidden_view(view2) try: @@ -1238,7 +1446,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 +1461,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): # pragma: no cover + 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): # pragma: no cover + 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 +1503,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 +1518,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 +1533,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 +1546,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 +1558,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 +1576,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 +1605,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 +1688,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 +1746,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 +1767,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 +1788,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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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 +2061,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 +2414,80 @@ 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..d6f45608d 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): # pragma: no cover + pass + + def pred2(context, request): # pragma: no cover + 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..5ebd78f8d 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): # pragma: no cover + 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..ce6659667 100644 --- a/tests/test_config/test_testing.py +++ b/tests/test_config/test_testing.py @@ -1,22 +1,28 @@ import unittest +from zope.interface import implementer 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 +32,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 +48,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 +62,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 +104,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 +114,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 +139,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 +158,78 @@ 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..805310c9a 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): # pragma: no cover + return handler + + def factory2(handler, registry): # pragma: no cover + 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..50d143b2d 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 + from pyramid.config.predicates import XHRPredicate # noqa: F401 + 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): # pragma: no cover + 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..977944fdd 100644 --- a/tests/test_config/test_views.py +++ b/tests/test_config/test_views.py @@ -1,33 +1,40 @@ import os import unittest +from zope.interface import implementer + from pyramid import testing +from pyramid.compat import im_func, text_ +from pyramid.exceptions import ConfigurationError +from pyramid.exceptions import ConfigurationExecutionError +from pyramid.exceptions import ConfigurationConflictError +from pyramid.interfaces import IResponse, IRequest, IMultiView from . import IDummy - from . import dummy_view -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 +45,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 +71,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 +99,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 +149,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 +159,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 +207,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 +219,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 +229,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 +240,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 +263,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 +295,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 +318,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 +333,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 +347,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 +361,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 +376,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 +384,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 +395,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 +415,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 +429,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 +438,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 +464,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 +479,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 +489,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 +508,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 +527,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 +550,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 +578,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 +587,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 +615,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 +639,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 +671,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 +697,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 +729,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 +749,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 +781,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 +801,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 +833,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 +856,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): # pragma: no cover + 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 +881,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): # pragma: no cover + 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 +910,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 +954,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 +985,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 +1027,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 +1049,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 +1094,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 +1140,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 +1173,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 +1212,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 +1278,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 +1292,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 +1306,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): # pragma: no cover + 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) 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 +1367,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): # pragma: no cover + 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 +1398,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 +1421,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 +1443,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 +1496,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 +1517,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 +1538,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 +1553,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 +1572,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 +1581,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 +1630,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 +1643,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 +1665,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 +1678,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 +1698,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 +1715,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 +1746,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 +1761,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 +1781,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 +1817,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 +1838,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 +1858,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 +1879,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 +1900,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 +1918,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 +1941,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 +1963,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 +1987,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 +2013,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 +2030,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 +2048,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): # pragma: no cover + return 'OK' + config = self._makeOne(autocommit=True) config.add_view(view, require_csrf=True, renderer=null_renderer) view = self._getViewCallable(config) @@ -1697,21 +2065,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 +2093,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 +2122,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 +2141,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 +2163,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 +2188,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 +2207,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,50 +2224,41 @@ 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): from pyramid.renderers import null_renderer - from zope.interface import directlyProvides from pyramid.exceptions import ConfigurationError config = self._makeOne(autocommit=True) + class DummyViewClass(object): - def run(self): pass + def run(self): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + raise AssertionError + + def view1(context, request): # pragma: no cover + raise AssertionError + view1.__permitted__ = lambda c, r: 'OK' - def view2(context, request): raise AssertionError + + def view2(context, request): # pragma: no cover + 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): # pragma: no cover + raise AssertionError + + def view1(context, request): # pragma: no cover + raise AssertionError + view1.__permitted__ = errfn - def view2(context, request): raise AssertionError + + def view2(context, request): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + pass + + def bleh(self): # pragma: no cover + 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(): # pragma: no cover + pass + + def view2(): # pragma: no cover + pass + + def view3(): # pragma: no cover + 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(): # pragma: no cover + pass + + def view2(): # pragma: no cover + pass + + def view3(): # pragma: no cover + 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): # pragma: no cover + pass + + def view2(request): # pragma: no cover + 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): # pragma: no cover + pass + view1.__original_view__ = 'abc' - def view2(context, request): pass + + def view2(context, request): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + pass + view.__text__ = 'some text' result = self._callFUT(view) self.assertEqual(result, 'some text') def test_without_text(self): - def view(): pass + def view(): # pragma: no cover + 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,6 @@ 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, - ) @implementer(IResponse) class DummyResponse(object): @@ -3504,10 +4234,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 +4249,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 +4269,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 +4290,23 @@ 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 +4315,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 +4339,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 +4359,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..25ed5fc0d 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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..78891200d 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -1,16 +1,16 @@ # -*- coding: utf-8 -*- -# import os +import unittest +from pyramid import testing here = os.path.dirname(__file__) 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 +19,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 +32,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 +47,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 +83,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 +102,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 +121,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 +131,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 +142,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 +155,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 +165,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 +174,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 +184,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 +242,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 +250,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 +260,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 +286,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 +310,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 +353,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 +435,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 +456,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 +466,7 @@ class TestLocalizerRequestMixin(unittest.TestCase): def _makeOne(self): from pyramid.i18n import LocalizerRequestMixin + request = LocalizerRequestMixin() request.registry = self.config.registry request.cookies = {} @@ -441,12 +476,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 +491,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 +501,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..28160eb7a 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1,43 +1,44 @@ # -*- coding: utf-8 -*- - import datetime import gc import locale import os import unittest +from webtest import TestApp +from zope.interface import Interface 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 +from .pkgs.exceptionviewapp.models import AnException, NotAnException # 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) + self.assertIsInstance(wsgiapptest, types.FunctionType) context = DummyContext() request = DummyRequest() result = wsgiapptest(context, request) @@ -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,13 @@ 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 + # 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 +461,12 @@ 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 + # 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 +479,14 @@ 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..163bb85aa 100644 --- a/tests/test_location.py +++ b/tests/test_location.py @@ -1,15 +1,22 @@ import unittest +from zope.interface import implementer +from pyramid.interfaces import ILocation + 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 +25,27 @@ 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..aee4f0e15 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -1,10 +1,14 @@ import unittest +from zope.interface import Interface +from zope.interface import implementer + 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 +39,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 +53,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 +72,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 +83,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 +104,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 +113,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 +143,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 +154,7 @@ class TestIntrospector(unittest.TestCase): def test_get_category_with_sortkey(self): import operator + inst = self._makeOne() intr = DummyIntrospectable() intr.foo = 2 @@ -151,15 +165,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 +185,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 +213,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 +243,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 +270,8 @@ class TestIntrospector(unittest.TestCase): KeyError, inst.relate, ('category', 'discriminator'), - ('category2', 'discriminator2') - ) + ('category2', 'discriminator2'), + ) def test_unrelate(self): inst = self._makeOne() @@ -250,18 +282,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 +313,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 +327,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 +350,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 +370,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 +398,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 +423,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' @@ -390,12 +443,10 @@ class DummyIntrospectable(object): return hash((self.category_name,) + (self.discriminator,)) -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..dcac501aa 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -1,17 +1,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 +14,7 @@ class TestRequest(unittest.TestCase): def _getTargetClass(self): from pyramid.request import Request + return Request def _makeOne(self, environ=None): @@ -32,26 +25,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 +59,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 +115,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 +131,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() @@ -148,18 +152,22 @@ class TestRequest(unittest.TestCase): def test__process_response_callback_adding_response_callback(self): """ - When a response callback adds another callback, that new callback should still be called. + When a response callback adds another callback, that new callback + should still be called. 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..5231e47f0 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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..3e66757f6 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -1,6 +1,9 @@ import unittest +from zope.interface import implementer from pyramid import testing +from pyramid.interfaces import IResponse + class TestRouter(unittest.TestCase): def setUp(self): @@ -13,6 +16,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 +24,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 +33,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 +76,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 +126,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 +152,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 +166,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 +221,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 +233,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 +243,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 +256,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 +266,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 +279,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 +293,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 +308,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 +318,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 +333,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 +349,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 +374,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 +390,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 +410,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 +433,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 +463,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 +496,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 +520,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 +544,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 +568,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 +601,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 +630,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 +659,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 +688,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 +702,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 +733,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 +756,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 +786,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 +818,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 +861,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 +871,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 +893,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 +914,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 +941,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 +965,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 +986,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 +1020,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 +1034,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 +1049,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 +1063,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 +1079,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 +1093,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 +1108,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 +1132,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 +1155,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 +1178,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 +1186,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 +1203,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 +1211,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 +1227,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 +1235,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 +1252,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 +1266,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 +1282,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 +1296,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 +1313,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 +1327,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 +1343,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 +1351,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 +1377,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 +1386,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 +1402,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 +1411,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 +1426,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 +1439,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 +1475,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 +1516,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 +1549,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 +1565,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 +1599,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 +1622,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 +1633,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 +1642,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 +1667,7 @@ class DummyView: raise self.raise_exception return self.response + class DummyRootFactory: def __init__(self, root): self.root = root @@ -1365,21 +1675,22 @@ 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 +1698,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..8f74f35f8 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): @@ -114,12 +121,13 @@ class Test_prepare(unittest.TestCase): request.context = context registry = request.registry = self._makeRegistry() info = self._callFUT(request=request, registry=registry) - root, closer, root = info['root'], info['closer'], info['root'] + closer = info['closer'] closer() self.assertEqual(request.context, context) 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') @@ -128,7 +136,7 @@ class Test_prepare(unittest.TestCase): registry = request.registry = self._makeRegistry([exts, DummyFactory]) info = self._callFUT(request=request, registry=registry) self.assertEqual(request.foo, 'bar') - root, closer = info['root'], info['closer'] + closer = info['closer'] closer() def test_it_is_a_context_manager(self): @@ -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..8e340f645 100644 --- a/tests/test_scripts/dummy.py +++ b/tests/test_scripts/dummy.py @@ -1,23 +1,34 @@ +from zope.interface import implementer +from pyramid.interfaces import IMultiView + + class DummyTweens(object): def __init__(self, implicit, explicit): 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 +41,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 +60,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 +77,46 @@ 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): # pragma: no cover + 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..5e3f359f6 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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,22 @@ 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 +464,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:]): @@ -457,7 +484,6 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(data, expected[index]) 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 +495,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): # pragma: no cover + 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 +521,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b', request_method='GET') @@ -518,7 +537,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 +549,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 +560,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -548,7 +569,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 +581,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 +592,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): # pragma: no cover + return 'view1' + + def view2(context, request): # pragma: no cover + return 'view2' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -579,7 +604,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 +612,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 +626,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 +637,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -619,7 +646,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 +668,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -649,7 +677,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 +698,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -678,7 +707,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 +716,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 +732,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -710,7 +741,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 +750,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 +766,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): # pragma: no cover + return 'view1' config = self._makeConfig(autocommit=True) config.add_route('foo', '/a/b') @@ -742,7 +775,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 +784,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) @@ -763,8 +797,6 @@ class TestPRoutesCommand(unittest.TestCase): self.assertEqual(L[0].split(), ['Method', 'Name']) def test_static_routes_included_in_list(self): - from pyramid.renderers import null_renderer as nr - config = self._makeConfig(autocommit=True) config.add_route('foo', 'http://example.com/bar.aspx', static=True) @@ -776,15 +808,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..ee50887f6 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,21 @@ 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..0b26a9cf3 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + pass + + def view2(): # pragma: no cover + 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(): # pragma: no cover + pass + + def view2(): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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..90e30c94f 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -1,20 +1,26 @@ import unittest from zope.component import getSiteManager +from zope.interface import Interface +from zope.interface import implementer 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 +39,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 +105,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 +117,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 +134,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 +164,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 +193,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 +232,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 +244,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 +263,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 +279,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 +322,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 +359,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 +374,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 +394,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 +402,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 +440,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 +457,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 +482,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 +503,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 +544,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(): # pragma: no cover + 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 +608,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 +667,35 @@ 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 +705,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 +714,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..61e480cbc 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,26 @@ 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" + u"-._~!$&'()*+,;=:@" + ) 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 +1252,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 +1273,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 +1303,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..054f4360d 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): # pragma: no cover + 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..94a0a61c9 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -1,13 +1,10 @@ import os import unittest -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 +12,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 +33,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 +59,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 +68,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 +91,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 +161,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 +196,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 +206,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 +218,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 +230,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 +242,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 +283,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 +303,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 +317,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 +339,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 +368,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 +392,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 +411,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 +430,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 +471,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 +506,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 +589,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 +649,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 +695,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 +726,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 +739,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 +796,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 +831,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 +845,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 +861,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 +876,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 +1087,7 @@ class Test_route_url(unittest.TestCase): self.elements = elements self.kw = kw return 'route url' + return Request() def test_it(self): @@ -1026,11 +1096,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 +1112,7 @@ class Test_route_path(unittest.TestCase): self.elements = elements self.kw = kw return 'route path' + return Request() def test_it(self): @@ -1048,11 +1121,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 +1137,7 @@ class Test_resource_url(unittest.TestCase): self.elements = elements self.kw = kw return 'resource url' + return Request() def test_it(self): @@ -1070,11 +1146,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 +1161,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 +1169,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 +1198,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 +1206,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 +1235,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 +1243,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 +1258,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 +1266,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 +1278,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 +1286,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 +1303,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 +1328,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 +1360,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 +1388,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 +1396,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 +1409,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 +1444,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..57f81b527 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,35 +15,39 @@ 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') self.assertEqual(route.name, 'name') self.assertEqual(route.factory, 'factory') - self.assertTrue(route.generate.__class__ is types.FunctionType) - self.assertTrue(route.match.__class__ is types.FunctionType) + self.assertIsInstance(route.generate, types.FunctionType) + self.assertIsInstance(route.match, types.FunctionType) def test_ctor_defaults(self): import types + route = self._makeOne('name', ':path') self.assertEqual(route.pattern, ':path') self.assertEqual(route.path, ':path') self.assertEqual(route.name, 'name') self.assertEqual(route.factory, None) - self.assertTrue(route.generate.__class__ is types.FunctionType) - self.assertTrue(route.match.__class__ is types.FunctionType) + self.assertIsInstance(route.generate, types.FunctionType) + self.assertIsInstance(route.match, types.FunctionType) 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')}) - #'/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}', '/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')}, + ) # '/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')}) - #'/La%20Pe%C3%B1a' + 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..a36655f6f 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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..f82480169 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -1,11 +1,12 @@ import unittest -import sys - +from zope.interface import Interface from zope.interface import implementer +import sys from pyramid import testing - from pyramid.interfaces import IRequest +from pyramid.interfaces import IResponse + class BaseTest(object): def setUp(self): @@ -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): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + pass + + def bar(self): # pragma: no cover + 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): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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(): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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,8 +1209,7 @@ class DummyRequest: if environ is None: environ = {} self.environ = environ - -from pyramid.interfaces import IResponse + @implementer(IResponse) class DummyResponse(object): @@ -1015,21 +1217,24 @@ class DummyResponse(object): 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 +1246,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 +1265,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..a1455ed92 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,30 @@ 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,10 +116,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) response = result(None, None) @@ -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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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() @@ -1556,7 +1879,7 @@ class TestAddDeriver(unittest.TestCase): self.assertFalse(response.deriv) self.config.add_view_deriver(deriv, 'test_deriv') - result = self.config._derive_view(view) + result = self.config._derive_view(view) # noqa: F841 self.assertTrue(response.deriv) def test_override_deriver(self): @@ -1583,12 +1906,13 @@ class TestAddDeriver(unittest.TestCase): flags.clear() view2 = AView() self.config.add_view_deriver(deriv2, 'test_deriv') - result = self.config._derive_view(view2) + result = self.config._derive_view(view2) # noqa: F841 self.assertFalse(flags.get('deriv1')) self.assertTrue(flags.get('deriv2')) 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) - result = self.config._derive_view(view) + deriv1, name='mapped_view', under='rendered_view', over=VIEW + ) + result = self.config._derive_view(view) # noqa: F841 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 = [] @@ -1627,12 +1953,15 @@ class TestAddDeriver(unittest.TestCase): self.config.add_view_deriver(deriv1, 'deriv1') self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1') self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1') - result = self.config._derive_view(view) + result = self.config._derive_view(view) # noqa: F841 self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2']) def test_add_deriver_without_name(self): from pyramid.interfaces import IViewDerivers - def deriv1(view, info): pass + + def deriv1(view, info): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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): # pragma: no cover + 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 - @@ -17,7 +17,7 @@ basepython = pypy: pypy pypy3: pypy3 py2: python2.7 - py3: python3.5 + py3: python3.6 commands = nosetests --with-xunit --xunit-file=nosetests-{envname}.xml {posargs:} @@ -63,13 +63,15 @@ deps = virtualenv [testenv:lint] skip_install = true -basepython = python3.5 +basepython = python3.6 commands = - flake8 pyramid/ + flake8 src/pyramid tests setup.py + black --check --diff src/pyramid tests setup.py python setup.py check -r -s -m check-manifest deps = flake8 + black readme_renderer check-manifest @@ -113,7 +115,7 @@ extras = [testenv:coverage] skip_install = true -basepython = python3.5 +basepython = python3.6 commands = coverage erase coverage combine @@ -124,6 +126,14 @@ deps = setenv = COVERAGE_FILE=.coverage +[testenv:black] +skip_install = true +basepython = python3.6 +commands = + black src/pyramid tests setup.py +deps = + black + [testenv:build] skip_install = true basepython = python3.6 |
