summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-16 22:05:17 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-16 22:05:17 +0000
commite06153d2a851513c435b9f7dc2a5d8f3a1191405 (patch)
treef64ffefb1dc6b0894f3a254e919f48148f330b49
parent58fdd1e948b7223cbcaf4fdceb159de200356d79 (diff)
downloadpyramid-e06153d2a851513c435b9f7dc2a5d8f3a1191405.tar.gz
pyramid-e06153d2a851513c435b9f7dc2a5d8f3a1191405.tar.bz2
pyramid-e06153d2a851513c435b9f7dc2a5d8f3a1191405.zip
Failing one test.
-rw-r--r--repoze/bfg/registry.py265
-rw-r--r--repoze/bfg/renderers.py10
-rw-r--r--repoze/bfg/tests/test_registry.py373
-rw-r--r--repoze/bfg/tests/test_view.py1049
-rw-r--r--repoze/bfg/view.py388
5 files changed, 1091 insertions, 994 deletions
diff --git a/repoze/bfg/registry.py b/repoze/bfg/registry.py
index dfd940af5..95a6d6608 100644
--- a/repoze/bfg/registry.py
+++ b/repoze/bfg/registry.py
@@ -1,5 +1,9 @@
+import os
import re
import sys
+import inspect
+
+from webob import Response
from zope.component.registry import Components
@@ -19,19 +23,30 @@ from repoze.bfg.interfaces import INotFoundView
from repoze.bfg.interfaces import IPackageOverrides
from repoze.bfg.interfaces import IRendererFactory
from repoze.bfg.interfaces import IRequest
+from repoze.bfg.interfaces import IResponseFactory
from repoze.bfg.interfaces import IRouteRequest
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import ISecuredView
from repoze.bfg.interfaces import IView
from repoze.bfg.interfaces import IViewPermission
-
+from repoze.bfg.interfaces import ILogger
+
+from repoze.bfg import chameleon_zpt
+from repoze.bfg import chameleon_text
+from repoze.bfg import renderers
+from repoze.bfg.compat import all
+from repoze.bfg.exceptions import NotFound
+from repoze.bfg.exceptions import Forbidden
from repoze.bfg.request import route_request_iface
from repoze.bfg.resource import PackageOverrides
+from repoze.bfg.settings import get_settings
from repoze.bfg.static import StaticRootFactory
from repoze.bfg.traversal import find_interface
-from repoze.bfg.view import MultiView
-from repoze.bfg.view import derive_view
from repoze.bfg.view import static as static_view
+from repoze.bfg.view import render_view_to_response
+from repoze.bfg.view import requestonly
+from repoze.bfg.view import decorate_view
+from repoze.bfg.view import MultiView
from repoze.bfg.urldispatch import RoutesRootFactory
class Registry(Components, dict):
@@ -44,6 +59,10 @@ class Registry(Components, dict):
Components.__init__(self, name=name, bases=bases)
mapper = RoutesRootFactory(DefaultRootFactory)
self.registerUtility(mapper, IRoutesMapper)
+ self.renderer(chameleon_zpt.renderer_factory, '.pt')
+ self.renderer(chameleon_text.renderer_factory, '.txt')
+ self.renderer(renderers.json_renderer_factory, 'json')
+ self.renderer(renderers.string_renderer_factory, 'string')
def registerSubscriptionAdapter(self, *arg, **kw):
result = Components.registerSubscriptionAdapter(self, *arg, **kw)
@@ -94,8 +113,8 @@ class Registry(Components, dict):
request_param=request_param, header=header, accept=accept,
containment=containment)
- derived_view = derive_view(view, permission, predicates, attr,
- renderer, wrapper, name)
+ derived_view = self.derive_view(view, permission, predicates, attr,
+ renderer, wrapper, name)
r_for_ = for_
r_request_type = request_type
if r_for_ is None:
@@ -142,6 +161,238 @@ class Registry(Components, dict):
(for_, request_type), IViewPermission,
name, info=_info)
+ def map_view(self, view, attr=None, renderer_name=None):
+ wrapped_view = view
+
+ renderer = None
+
+ if renderer_name is None:
+ # global default renderer
+ factory = self.queryUtility(IRendererFactory)
+ if factory is not None:
+ renderer_name = ''
+ renderer = factory(renderer_name)
+ else:
+ renderer = self.renderer_from_name(renderer_name)
+
+ if inspect.isclass(view):
+ # If the object we've located is a class, turn it into a
+ # function that operates like a Zope view (when it's invoked,
+ # construct an instance using 'context' and 'request' as
+ # position arguments, then immediately invoke the __call__
+ # method of the instance with no arguments; __call__ should
+ # return an IResponse).
+ if requestonly(view, attr):
+ # its __init__ accepts only a single request argument,
+ # instead of both context and request
+ def _bfg_class_requestonly_view(context, request):
+ inst = view(request)
+ if attr is None:
+ response = inst()
+ else:
+ response = getattr(inst, attr)()
+ if renderer is not None:
+ response = self.rendered_response(renderer,
+ response, inst,
+ context, request,
+ renderer_name)
+ return response
+ wrapped_view = _bfg_class_requestonly_view
+ else:
+ # its __init__ accepts both context and request
+ def _bfg_class_view(context, request):
+ inst = view(context, request)
+ if attr is None:
+ response = inst()
+ else:
+ response = getattr(inst, attr)()
+ if renderer is not None:
+ response = self.rendered_response(renderer,
+ response, inst,
+ context, request,
+ renderer_name)
+ return response
+ wrapped_view = _bfg_class_view
+
+ elif requestonly(view, attr):
+ # its __call__ accepts only a single request argument,
+ # instead of both context and request
+ def _bfg_requestonly_view(context, request):
+ if attr is None:
+ response = view(request)
+ else:
+ response = getattr(view, attr)(request)
+
+ if renderer is not None:
+ response = self.rendered_response(renderer,
+ response, view,
+ context, request,
+ renderer_name)
+ return response
+ wrapped_view = _bfg_requestonly_view
+
+ elif attr:
+ def _bfg_attr_view(context, request):
+ response = getattr(view, attr)(context, request)
+ if renderer is not None:
+ response = self.rendered_response(renderer,
+ response, view,
+ context, request,
+ renderer_name)
+ return response
+ wrapped_view = _bfg_attr_view
+
+ elif renderer is not None:
+ def _rendered_view(context, request):
+ response = view(context, request)
+ response = self.rendered_response(renderer,
+ response, view,
+ context, request,
+ renderer_name)
+ return response
+ wrapped_view = _rendered_view
+
+ decorate_view(wrapped_view, view)
+ return wrapped_view
+
+ def renderer_from_name(self, path):
+ name = os.path.splitext(path)[1]
+ if not name:
+ name = path
+ factory = self.queryUtility(IRendererFactory, name=name)
+ if factory is None:
+ raise ValueError('No renderer for renderer name %r' % name)
+ return factory(path)
+
+ def rendered_response(self, renderer, response, view, context,request,
+ renderer_name):
+ if ( hasattr(response, 'app_iter') and hasattr(response, 'headerlist')
+ and hasattr(response, 'status') ):
+ return response
+ result = renderer(response, {'view':view, 'renderer_name':renderer_name,
+ 'context':context, 'request':request})
+ response_factory = self.queryUtility(IResponseFactory, default=Response)
+ response = response_factory(result)
+ attrs = request.__dict__
+ content_type = attrs.get('response_content_type', None)
+ if content_type is not None:
+ response.content_type = content_type
+ headerlist = attrs.get('response_headerlist', None)
+ if headerlist is not None:
+ for k, v in headerlist:
+ response.headers.add(k, v)
+ status = attrs.get('response_status', None)
+ if status is not None:
+ response.status = status
+ charset = attrs.get('response_charset', None)
+ if charset is not None:
+ response.charset = charset
+ cache_for = attrs.get('response_cache_for', None)
+ if cache_for is not None:
+ response.cache_expires = cache_for
+ return response
+
+ def derive_view(self, original_view, permission=None, predicates=(),
+ attr=None, renderer_name=None, wrapper_viewname=None,
+ viewname=None):
+ mapped_view = self.map_view(original_view, attr, renderer_name)
+ owrapped_view = self.owrap_view(mapped_view, viewname, wrapper_viewname)
+ secured_view = self.secure_view(owrapped_view, permission)
+ debug_view = self.authdebug_view(secured_view, permission)
+ derived_view = self.predicate_wrap(debug_view, predicates)
+ return derived_view
+
+ def owrap_view(self, view, viewname, wrapper_viewname):
+ 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)
+ if wrapped_response is None:
+ raise ValueError(
+ 'No wrapper view named %r found when executing view '
+ 'named %r' % (wrapper_viewname, viewname))
+ return wrapped_response
+ decorate_view(_owrapped_view, view)
+ return _owrapped_view
+
+ def predicate_wrap(self, view, predicates):
+ if not predicates:
+ return view
+ def _wrapped(context, request):
+ if all((predicate(context, request) for predicate in predicates)):
+ return view(context, request)
+ raise NotFound('predicate mismatch for view %s' % view)
+ def checker(context, request):
+ return all((predicate(context, request) for predicate in
+ predicates))
+ _wrapped.__predicated__ = checker
+ decorate_view(_wrapped, view)
+ return _wrapped
+
+ def secure_view(self, view, permission):
+ wrapped_view = view
+ authn_policy = self.queryUtility(IAuthenticationPolicy)
+ authz_policy = self.queryUtility(IAuthorizationPolicy)
+ if authn_policy and authz_policy and (permission is not None):
+ def _secured_view(context, request):
+ principals = authn_policy.effective_principals(request)
+ if authz_policy.permits(context, principals, permission):
+ return view(context, request)
+ msg = getattr(request, 'authdebug_message',
+ 'Unauthorized: %s failed permission check' % view)
+ raise Forbidden(msg)
+ _secured_view.__call_permissive__ = view
+ def _permitted(context, request):
+ principals = authn_policy.effective_principals(request)
+ return authz_policy.permits(context, principals, permission)
+ _secured_view.__permitted__ = _permitted
+ wrapped_view = _secured_view
+ decorate_view(wrapped_view, view)
+
+ return wrapped_view
+
+ def authdebug_view(self, view, permission):
+ wrapped_view = view
+ authn_policy = self.queryUtility(IAuthenticationPolicy)
+ authz_policy = self.queryUtility(IAuthorizationPolicy)
+ settings = get_settings()
+ debug_authorization = False
+ if settings is not None:
+ debug_authorization = settings.get('debug_authorization', False)
+ if debug_authorization:
+ def _authdebug_view(context, request):
+ view_name = getattr(request, 'view_name', None)
+
+ if authn_policy and authz_policy:
+ if permission is None:
+ msg = 'Allowed (no permission registered)'
+ else:
+ principals = authn_policy.effective_principals(request)
+ 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))
+ logger = self.queryUtility(ILogger, 'repoze.bfg.debug')
+ logger and logger.debug(msg)
+ if request is not None:
+ request.authdebug_message = msg
+ return view(context, request)
+
+ wrapped_view = _authdebug_view
+ decorate_view(wrapped_view, view)
+
+ return wrapped_view
+
def route(self, name, path, view=None, view_for=None,
permission=None, factory=None, request_type=None, for_=None,
header=None, xhr=False, accept=None, path_info=None,
@@ -288,8 +539,8 @@ class Registry(Components, dict):
raise ConfigurationError('"view" attribute was not specified and '
'no renderer specified')
- derived_view = derive_view(view, attr=attr, renderer_name=renderer,
- wrapper_viewname=wrapper)
+ derived_view = self.derive_view(view, attr=attr, renderer_name=renderer,
+ wrapper_viewname=wrapper)
self.registerUtility(derived_view, iface, '', info=_info)
def static(self, name, path, cache_max_age=3600, _info=u''):
diff --git a/repoze/bfg/renderers.py b/repoze/bfg/renderers.py
index 212c02dcf..b5dfad523 100644
--- a/repoze/bfg/renderers.py
+++ b/repoze/bfg/renderers.py
@@ -4,7 +4,6 @@ import pkg_resources
from zope.component import getSiteManager
from zope.component import queryUtility
-from repoze.bfg.interfaces import IRendererFactory
from repoze.bfg.interfaces import ITemplateRenderer
from repoze.bfg.compat import json
@@ -63,13 +62,8 @@ def template_renderer_factory(path, impl, level=3):
return renderer
def renderer_from_name(path):
- name = os.path.splitext(path)[1]
- if not name:
- name = path
- factory = queryUtility(IRendererFactory, name=name)
- if factory is None:
- raise ValueError('No renderer for renderer name %r' % name)
- return factory(path)
+ sm = getSiteManager()
+ return sm.renderer_from_name(path)
def _reload_resources():
settings = get_settings()
diff --git a/repoze/bfg/tests/test_registry.py b/repoze/bfg/tests/test_registry.py
index 3eada7b1c..11f5cbf3a 100644
--- a/repoze/bfg/tests/test_registry.py
+++ b/repoze/bfg/tests/test_registry.py
@@ -61,6 +61,355 @@ class TestRegistry(unittest.TestCase):
self.assertEqual(overrides.inserted, [('path', 'opackage', 'oprefix')])
self.assertEqual(overrides.package, package)
+ def _registerRenderer(self, reg, name='.txt'):
+ from repoze.bfg.interfaces import IRendererFactory
+ from repoze.bfg.interfaces import ITemplateRenderer
+ from zope.interface import implements
+ class Renderer:
+ implements(ITemplateRenderer)
+ def __init__(self, path):
+ pass
+ def __call__(self, *arg):
+ return 'Hello!'
+ reg.registerUtility(Renderer, IRendererFactory, name=name)
+
+ def test_map_view_as_function_context_and_request(self):
+ def view(context, request):
+ return 'OK'
+ reg = self._makeOne()
+ result = reg.map_view(view)
+ self.failUnless(result is view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_function_with_attr(self):
+ def view(context, request):
+ """ """
+ reg = self._makeOne()
+ result = reg.map_view(view, attr='__name__')
+ self.failIf(result is view)
+ self.assertRaises(TypeError, result, None, None)
+
+ def test_map_view_as_function_with_attr_and_renderer(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ def view(context, request):
+ """ """
+ result = reg.map_view(view, attr='__name__',
+ renderer_name='fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertRaises(TypeError, result, None, None)
+
+ def test_map_view_as_function_requestonly(self):
+ reg = self._makeOne()
+ def view(request):
+ return 'OK'
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_function_requestonly_with_attr(self):
+ reg = self._makeOne()
+ def view(request):
+ """ """
+ result = reg.map_view(view, attr='__name__')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertRaises(TypeError, result, None, None)
+
+ def test_map_view_as_newstyle_class_context_and_request(self):
+ reg = self._makeOne()
+ class view(object):
+ def __init__(self, context, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_newstyle_class_context_and_request_with_attr(self):
+ reg = self._makeOne()
+ class view(object):
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return 'OK'
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_newstyle_class_context_and_request_attr_and_renderer(
+ self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class view(object):
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_as_newstyle_class_requestonly(self):
+ reg = self._makeOne()
+ class view(object):
+ def __init__(self, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_newstyle_class_requestonly_with_attr(self):
+ reg = self._makeOne()
+ class view(object):
+ def __init__(self, request):
+ pass
+ def index(self):
+ return 'OK'
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_newstyle_class_requestonly_with_attr_and_renderer(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class view(object):
+ def __init__(self, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_as_oldstyle_class_context_and_request(self):
+ reg = self._makeOne()
+ class view:
+ def __init__(self, context, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_oldstyle_class_context_and_request_with_attr(self):
+ reg = self._makeOne()
+ class view:
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return 'OK'
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_oldstyle_class_context_and_request_attr_and_renderer(
+ self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class view:
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_as_oldstyle_class_requestonly(self):
+ reg = self._makeOne()
+ class view:
+ def __init__(self, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_oldstyle_class_requestonly_with_attr(self):
+ reg = self._makeOne()
+ class view:
+ def __init__(self, request):
+ pass
+ def index(self):
+ return 'OK'
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_oldstyle_class_requestonly_attr_and_renderer(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class view:
+ def __init__(self, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_as_instance_context_and_request(self):
+ reg = self._makeOne()
+ class View:
+ def __call__(self, context, request):
+ return 'OK'
+ view = View()
+ result = reg.map_view(view)
+ self.failUnless(result is view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_instance_context_and_request_and_attr(self):
+ reg = self._makeOne()
+ class View:
+ def index(self, context, request):
+ return 'OK'
+ view = View()
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_instance_context_and_request_attr_and_renderer(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class View:
+ def index(self, context, request):
+ return {'a':'1'}
+ view = View()
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_as_instance_requestonly(self):
+ reg = self._makeOne()
+ class View:
+ def __call__(self, request):
+ return 'OK'
+ view = View()
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.failUnless('instance' in result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_instance_requestonly_with_attr(self):
+ reg = self._makeOne()
+ class View:
+ def index(self, request):
+ return 'OK'
+ view = View()
+ result = reg.map_view(view, attr='index')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.failUnless('instance' in result.__name__)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_map_view_as_instance_requestonly_with_attr_and_renderer(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ class View:
+ def index(self, request):
+ return {'a':'1'}
+ view = View()
+ result = reg.map_view(
+ view, attr='index',
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.failUnless('instance' in result.__name__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_rendereronly(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg)
+ def view(context, request):
+ return {'a':'1'}
+ result = reg.map_view(
+ view,
+ renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
+ def test_map_view_defaultrendereronly(self):
+ reg = self._makeOne()
+ self._registerRenderer(reg, name='')
+ def view(context, request):
+ return {'a':'1'}
+ result = reg.map_view(view)
+ self.failIf(result is view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ request = DummyRequest()
+ self.assertEqual(result(None, request).body, 'Hello!')
+
class TestBFGViewGrokker(unittest.TestCase):
def setUp(self):
cleanUp()
@@ -133,7 +482,6 @@ class TestDefaultRootFactory(unittest.TestCase):
self.assertEqual(root.a, 1)
self.assertEqual(root.b, 2)
-
class DummyModule:
__path__ = "foo"
__name__ = "dummy"
@@ -157,3 +505,26 @@ class DummyOverrides:
def insert(self, path, package, prefix):
self.inserted.append((path, package, prefix))
+
+class DummyRequest:
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+
+ def get_response(self, application):
+ return application
+
+ def copy(self):
+ self.copied = True
+ return self
+
+class DummyResponse:
+ status = '200 OK'
+ headerlist = ()
+ def __init__(self, body=None):
+ if body is None:
+ self.app_iter = ()
+ else:
+ self.app_iter = [body]
+
diff --git a/repoze/bfg/tests/test_view.py b/repoze/bfg/tests/test_view.py
index 80179e247..807dbe85a 100644
--- a/repoze/bfg/tests/test_view.py
+++ b/repoze/bfg/tests/test_view.py
@@ -526,698 +526,6 @@ class AppendSlashNotFoundView(unittest.TestCase):
self.assertEqual(response.status, '302 Found')
self.assertEqual(response.location, '/abc/')
-class TestMultiView(unittest.TestCase):
- def _getTargetClass(self):
- from repoze.bfg.view import MultiView
- return MultiView
-
- def _makeOne(self, name='name'):
- return self._getTargetClass()(name)
-
- def test_class_implements_ISecuredView(self):
- from zope.interface.verify import verifyClass
- from repoze.bfg.interfaces import ISecuredView
- verifyClass(ISecuredView, self._getTargetClass())
-
- def test_instance_implements_ISecuredView(self):
- from zope.interface.verify import verifyObject
- from repoze.bfg.interfaces import ISecuredView
- verifyObject(ISecuredView, self._makeOne())
-
- def test_add(self):
- mv = self._makeOne()
- mv.add('view', 100)
- self.assertEqual(mv.views, [(100, 'view')])
- mv.add('view2', 99)
- self.assertEqual(mv.views, [(99, 'view2'), (100, 'view')])
-
- def test_match_not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.match, context, request)
-
- def test_match_predicate_fails(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- def view(context, request):
- """ """
- view.__predicated__ = lambda *arg: False
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.match, context, request)
-
- def test_match_predicate_succeeds(self):
- mv = self._makeOne()
- def view(context, request):
- """ """
- view.__predicated__ = lambda *arg: True
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- result = mv.match(context, request)
- self.assertEqual(result, view)
-
- def test_permitted_no_views(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.__permitted__, context, request)
-
- def test_permitted_no_match_with__permitted__(self):
- mv = self._makeOne()
- def view(context, request):
- """ """
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- self.assertEqual(mv.__permitted__(None, None), True)
-
- def test_permitted(self):
- from zope.component import getSiteManager
- mv = self._makeOne()
- def view(context, request):
- """ """
- def permitted(context, request):
- return False
- view.__permitted__ = permitted
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- sm = getSiteManager()
- result = mv.__permitted__(context, request)
- self.assertEqual(result, False)
-
- def test__call__not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv, context, request)
-
- def test___call__intermediate_not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view1(context, request):
- raise NotFound
- def view2(context, request):
- return expected_response
- mv.views = [(100, view1), (99, view2)]
- response = mv(context, request)
- self.assertEqual(response, expected_response)
-
- def test___call__(self):
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view(context, request):
- return expected_response
- mv.views = [(100, view)]
- response = mv(context, request)
- self.assertEqual(response, expected_response)
-
- def test__call_permissive__not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv, context, request)
-
- def test___call_permissive_has_call_permissive(self):
- mv = self._makeOne()
- context = DummyContext()
- 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)]
- response = mv.__call_permissive__(context, request)
- self.assertEqual(response, expected_response)
-
- def test___call_permissive_has_no_call_permissive(self):
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view(context, request):
- return expected_response
- mv.views = [(100, view)]
- response = mv.__call_permissive__(context, request)
- self.assertEqual(response, expected_response)
-
-class Test_map_view(unittest.TestCase):
- def setUp(self):
- cleanUp()
-
- def tearDown(self):
- cleanUp()
-
- def _callFUT(self, view, *arg, **kw):
- from repoze.bfg.view import map_view
- return map_view(view, *arg, **kw)
-
- def _registerRenderer(self, name='.txt'):
- from repoze.bfg.interfaces import IRendererFactory
- from repoze.bfg.interfaces import ITemplateRenderer
- from zope.interface import implements
- from zope.component import getSiteManager
- class Renderer:
- implements(ITemplateRenderer)
- def __init__(self, path):
- pass
- def __call__(self, *arg):
- return 'Hello!'
- sm = getSiteManager()
- sm.registerUtility(Renderer, IRendererFactory, name=name)
-
- def test_view_as_function_context_and_request(self):
- def view(context, request):
- return 'OK'
- result = self._callFUT(view)
- self.failUnless(result is view)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_function_with_attr(self):
- def view(context, request):
- """ """
- result = self._callFUT(view, attr='__name__')
- self.failIf(result is view)
- self.assertRaises(TypeError, result, None, None)
-
- def test_view_as_function_with_attr_and_renderer(self):
- self._registerRenderer()
- def view(context, request):
- """ """
- result = self._callFUT(view, attr='__name__',
- renderer_name='fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertRaises(TypeError, result, None, None)
-
- def test_view_as_function_requestonly(self):
- def view(request):
- return 'OK'
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_function_requestonly_with_attr(self):
- def view(request):
- """ """
- result = self._callFUT(view, attr='__name__')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertRaises(TypeError, result, None, None)
-
- def test_view_as_newstyle_class_context_and_request(self):
- class view(object):
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_newstyle_class_context_and_request_with_attr(self):
- class view(object):
- def __init__(self, context, request):
- pass
- def index(self):
- return 'OK'
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_newstyle_class_context_and_request_with_attr_and_renderer(
- self):
- self._registerRenderer()
- class view(object):
- def __init__(self, context, request):
- pass
- def index(self):
- return {'a':'1'}
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_as_newstyle_class_requestonly(self):
- class view(object):
- def __init__(self, request):
- pass
- def __call__(self):
- return 'OK'
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_newstyle_class_requestonly_with_attr(self):
- class view(object):
- def __init__(self, request):
- pass
- def index(self):
- return 'OK'
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_newstyle_class_requestonly_with_attr_and_renderer(self):
- self._registerRenderer()
- class view(object):
- def __init__(self, request):
- pass
- def index(self):
- return {'a':'1'}
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_as_oldstyle_class_context_and_request(self):
- class view:
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_oldstyle_class_context_and_request_with_attr(self):
- class view:
- def __init__(self, context, request):
- pass
- def index(self):
- return 'OK'
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_oldstyle_class_context_and_request_with_attr_and_renderer(
- self):
- self._registerRenderer()
- class view:
- def __init__(self, context, request):
- pass
- def index(self):
- return {'a':'1'}
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_as_oldstyle_class_requestonly(self):
- class view:
- def __init__(self, request):
- pass
- def __call__(self):
- return 'OK'
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_oldstyle_class_requestonly_with_attr(self):
- class view:
- def __init__(self, request):
- pass
- def index(self):
- return 'OK'
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_oldstyle_class_requestonly_with_attr_and_renderer(self):
- self._registerRenderer()
- class view:
- def __init__(self, request):
- pass
- def index(self):
- return {'a':'1'}
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_as_instance_context_and_request(self):
- class View:
- def __call__(self, context, request):
- return 'OK'
- view = View()
- result = self._callFUT(view)
- self.failUnless(result is view)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_instance_context_and_request_and_attr(self):
- class View:
- def index(self, context, request):
- return 'OK'
- view = View()
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_instance_context_and_request_attr_and_renderer(self):
- self._registerRenderer()
- class View:
- def index(self, context, request):
- return {'a':'1'}
- view = View()
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_as_instance_requestonly(self):
- class View:
- def __call__(self, request):
- return 'OK'
- view = View()
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.failUnless('instance' in result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_instance_requestonly_with_attr(self):
- class View:
- def index(self, request):
- return 'OK'
- view = View()
- result = self._callFUT(view, attr='index')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.failUnless('instance' in result.__name__)
- self.assertEqual(result(None, None), 'OK')
-
- def test_view_as_instance_requestonly_with_attr_and_renderer(self):
- self._registerRenderer()
- class View:
- def index(self, request):
- return {'a':'1'}
- view = View()
- result = self._callFUT(
- view, attr='index',
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.failUnless('instance' in result.__name__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_rendereronly(self):
- self._registerRenderer()
- def view(context, request):
- return {'a':'1'}
- result = self._callFUT(
- view,
- renderer_name='repoze.bfg.tests:fixtures/minimal.txt')
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test_view_defaultrendereronly(self):
- self._registerRenderer(name='')
- def view(context, request):
- return {'a':'1'}
- result = self._callFUT(view)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- request = DummyRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
-class TestRequestOnly(unittest.TestCase):
- def _callFUT(self, arg):
- from repoze.bfg.view import requestonly
- return requestonly(arg)
-
- def test_newstyle_class_no_init(self):
- class foo(object):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_newstyle_class_init_toomanyargs(self):
- class foo(object):
- def __init__(self, context, request):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_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))
-
- 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), 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_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), True)
-
- def test_instance_toomanyargs(self):
- class Foo:
- def __call__(self, context, request):
- """ """
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
- def test_instance_defaultargs_onearg_named_request(self):
- class Foo:
- def __call__(self, request):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo))
-
- def test_instance_defaultargs_onearg_named_somethingelse(self):
- class Foo:
- def __call__(self, req):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo))
-
- def test_instance_defaultargs_firstname_not_request(self):
- class Foo:
- def __call__(self, context, request=None):
- """ """
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
- def test_instance_defaultargs_firstname_request(self):
- class Foo:
- def __call__(self, request, foo=1, bar=2):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo), True)
-
- def test_instance_nocall(self):
- class Foo: pass
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
-class TestDecorateView(unittest.TestCase):
- def _callFUT(self, wrapped, original):
- from repoze.bfg.view import decorate_view
- return decorate_view(wrapped, original)
-
- def test_it_same(self):
- def view(context, request):
- """ """
- result = self._callFUT(view, view)
- self.assertEqual(result, False)
-
- def test_it_different(self):
- class DummyView1:
- """ 1 """
- __name__ = '1'
- __module__ = '1'
- def __call__(self, context, request):
- """ """
- def __call_permissive__(self, context, reuqest):
- """ """
- def __predicated__(self, context, reuqest):
- """ """
- def __permitted__(self, context, request):
- """ """
- class DummyView2:
- """ 2 """
- __name__ = '2'
- __module__ = '2'
- def __call__(self, context, request):
- """ """
- def __call_permissive__(self, context, reuqest):
- """ """
- def __predicated__(self, context, reuqest):
- """ """
- def __permitted__(self, context, request):
- """ """
- view1 = DummyView1()
- view2 = DummyView2()
- result = self._callFUT(view1, view2)
- self.assertEqual(result, True)
- self.failUnless(view1.__doc__ is view2.__doc__)
- self.failUnless(view1.__module__ is view2.__module__)
- self.failUnless(view1.__name__ is view2.__name__)
- self.failUnless(view1.__call_permissive__.im_func is
- view2.__call_permissive__.im_func)
- self.failUnless(view1.__permitted__.im_func is
- view2.__permitted__.im_func)
- self.failUnless(view1.__predicated__.im_func is
- view2.__predicated__.im_func)
-
class Test_rendered_response(unittest.TestCase):
def setUp(self):
cleanUp()
@@ -1613,6 +921,363 @@ class TestDeriveView(unittest.TestCase):
inner_view, viewname='inner', wrapper_viewname='owrap')
result = self.assertRaises(ValueError, wrapped, None, request)
+class TestDecorateView(unittest.TestCase):
+ def _callFUT(self, wrapped, original):
+ from repoze.bfg.view import decorate_view
+ return decorate_view(wrapped, original)
+
+ def test_it_same(self):
+ def view(context, request):
+ """ """
+ result = self._callFUT(view, view)
+ self.assertEqual(result, False)
+
+ def test_it_different(self):
+ class DummyView1:
+ """ 1 """
+ __name__ = '1'
+ __module__ = '1'
+ def __call__(self, context, request):
+ """ """
+ def __call_permissive__(self, context, reuqest):
+ """ """
+ def __predicated__(self, context, reuqest):
+ """ """
+ def __permitted__(self, context, request):
+ """ """
+ class DummyView2:
+ """ 2 """
+ __name__ = '2'
+ __module__ = '2'
+ def __call__(self, context, request):
+ """ """
+ def __call_permissive__(self, context, reuqest):
+ """ """
+ def __predicated__(self, context, reuqest):
+ """ """
+ def __permitted__(self, context, request):
+ """ """
+ view1 = DummyView1()
+ view2 = DummyView2()
+ result = self._callFUT(view1, view2)
+ self.assertEqual(result, True)
+ self.failUnless(view1.__doc__ is view2.__doc__)
+ self.failUnless(view1.__module__ is view2.__module__)
+ self.failUnless(view1.__name__ is view2.__name__)
+ self.failUnless(view1.__call_permissive__.im_func is
+ view2.__call_permissive__.im_func)
+ self.failUnless(view1.__permitted__.im_func is
+ view2.__permitted__.im_func)
+ self.failUnless(view1.__predicated__.im_func is
+ view2.__predicated__.im_func)
+
+class TestMultiView(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.bfg.view import MultiView
+ return MultiView
+
+ def _makeOne(self, name='name'):
+ return self._getTargetClass()(name)
+
+ def test_class_implements_ISecuredView(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import ISecuredView
+ verifyClass(ISecuredView, self._getTargetClass())
+
+ def test_instance_implements_ISecuredView(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import ISecuredView
+ verifyObject(ISecuredView, self._makeOne())
+
+ def test_add(self):
+ mv = self._makeOne()
+ mv.add('view', 100)
+ self.assertEqual(mv.views, [(100, 'view')])
+ mv.add('view2', 99)
+ self.assertEqual(mv.views, [(99, 'view2'), (100, 'view')])
+
+ def test_match_not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.match, context, request)
+
+ def test_match_predicate_fails(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ view.__predicated__ = lambda *arg: False
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.match, context, request)
+
+ def test_match_predicate_succeeds(self):
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ view.__predicated__ = lambda *arg: True
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ result = mv.match(context, request)
+ self.assertEqual(result, view)
+
+ def test_permitted_no_views(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.__permitted__, context, request)
+
+ def test_permitted_no_match_with__permitted__(self):
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertEqual(mv.__permitted__(None, None), True)
+
+ def test_permitted(self):
+ from zope.component import getSiteManager
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ def permitted(context, request):
+ return False
+ view.__permitted__ = permitted
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ sm = getSiteManager()
+ result = mv.__permitted__(context, request)
+ self.assertEqual(result, False)
+
+ def test__call__not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv, context, request)
+
+ def test___call__intermediate_not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view1(context, request):
+ raise NotFound
+ def view2(context, request):
+ return expected_response
+ mv.views = [(100, view1), (99, view2)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call__(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view(context, request):
+ return expected_response
+ mv.views = [(100, view)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test__call_permissive__not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv, context, request)
+
+ def test___call_permissive_has_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ 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)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call_permissive_has_no_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view(context, request):
+ return expected_response
+ mv.views = [(100, view)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+class TestRequestOnly(unittest.TestCase):
+ def _callFUT(self, arg):
+ from repoze.bfg.view import requestonly
+ return requestonly(arg)
+
+ def test_newstyle_class_no_init(self):
+ class foo(object):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_newstyle_class_init_toomanyargs(self):
+ class foo(object):
+ def __init__(self, context, request):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_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))
+
+ 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), 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_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), True)
+
+ def test_instance_toomanyargs(self):
+ class Foo:
+ def __call__(self, context, request):
+ """ """
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+ def test_instance_defaultargs_onearg_named_request(self):
+ class Foo:
+ def __call__(self, request):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo))
+
+ def test_instance_defaultargs_onearg_named_somethingelse(self):
+ class Foo:
+ def __call__(self, req):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo))
+
+ def test_instance_defaultargs_firstname_not_request(self):
+ class Foo:
+ def __call__(self, context, request=None):
+ """ """
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+ def test_instance_defaultargs_firstname_request(self):
+ class Foo:
+ def __call__(self, request, foo=1, bar=2):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo), True)
+
+ def test_instance_nocall(self):
+ class Foo: pass
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+
+
class DummyContext:
pass
diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py
index 734bb7f0a..4fc22000b 100644
--- a/repoze/bfg/view.py
+++ b/repoze/bfg/view.py
@@ -1,8 +1,8 @@
import cgi
-import inspect
import mimetypes
import os
import sys
+import inspect
# 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
@@ -26,22 +26,14 @@ from zope.deprecation import deprecated
from zope.interface import implements
from zope.interface.advice import getFrameInfo
-from repoze.bfg.interfaces import IAuthenticationPolicy
-from repoze.bfg.interfaces import IAuthorizationPolicy
-from repoze.bfg.interfaces import ILogger
from repoze.bfg.interfaces import IMultiView
-from repoze.bfg.interfaces import IRendererFactory
from repoze.bfg.interfaces import IResponseFactory
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import IView
-from repoze.bfg.compat import all
from repoze.bfg.exceptions import NotFound
-from repoze.bfg.exceptions import Forbidden
from repoze.bfg.path import caller_package
-from repoze.bfg.renderers import renderer_from_name
from repoze.bfg.resource import resource_spec
-from repoze.bfg.settings import get_settings
from repoze.bfg.static import PackageURLParser
# b/c imports
@@ -477,163 +469,76 @@ def default_forbidden_view(context, request):
def default_notfound_view(context, request):
return default_view(context, request, '404 Not Found')
-class MultiView(object):
- implements(IMultiView)
+def append_slash_notfound_view(context, request):
+ """For behavior like Django's ``APPEND_SLASH=True``, use this view
+ as the Not Found view in your application.
- def __init__(self, name):
- self.name = name
- self.views = []
+ When this view is the Not Found view (indicating that no view was
+ found), and any routes have been defined in the configuration of
+ your application, if the value of ``PATH_INFO`` does not already
+ end in a slash, and if the value of ``PATH_INFO`` *plus* a slash
+ matches any route's path, do an HTTP redirect to the
+ slash-appended PATH_INFO. Note that this will *lose* ``POST``
+ data information (turning it into a GET), so you shouldn't rely on
+ this to redirect POST requests.
- def add(self, view, score):
- self.views.append((score, view))
- self.views.sort()
+ Add the following to your application's ``configure.zcml`` to use
+ this view as the Not Found view::
- def match(self, context, request):
- for score, view in self.views:
- if not hasattr(view, '__predicated__'):
- return view
- if view.__predicated__(context, request):
- return view
- raise NotFound(self.name)
+ <notfound
+ view="repoze.bfg.view.append_slash_notfound_view"/>
- def __permitted__(self, context, request):
- view = self.match(context, request)
- if hasattr(view, '__permitted__'):
- return view.__permitted__(context, request)
- return True
+ See also :ref:`changing_the_notfound_view`.
- def __call_permissive__(self, context, request):
- view = self.match(context, request)
- view = getattr(view, '__call_permissive__', view)
- return view(context, request)
+ .. note:: This function is new as of :mod:`repoze.bfg` version 1.1.
- def __call__(self, context, request):
- for score, view in self.views:
- try:
- return view(context, request)
- except NotFound:
- continue
- raise NotFound(self.name)
+ """
+ path = request.environ.get('PATH_INFO', '/')
+ mapper = queryUtility(IRoutesMapper)
+ if mapper is not None and not path.endswith('/'):
+ slashpath = path + '/'
+ for route in mapper.get_routes():
+ if route.match(slashpath) is not None:
+ return HTTPFound(location=slashpath)
+ return default_view(context, request, '404 Not Found')
-def rendered_response(renderer, response, view, context,request, renderer_name):
- if ( hasattr(response, 'app_iter') and hasattr(response, 'headerlist') and
- hasattr(response, 'status') ):
- return response
- result = renderer(response, {'view':view, 'renderer_name':renderer_name,
- 'context':context, 'request':request})
- response_factory = queryUtility(IResponseFactory, default=Response)
- response = response_factory(result)
- attrs = request.__dict__
- content_type = attrs.get('response_content_type', None)
- if content_type is not None:
- response.content_type = content_type
- headerlist = attrs.get('response_headerlist', None)
- if headerlist is not None:
- for k, v in headerlist:
- response.headers.add(k, v)
- status = attrs.get('response_status', None)
- if status is not None:
- response.status = status
- charset = attrs.get('response_charset', None)
- if charset is not None:
- response.charset = charset
- cache_for = attrs.get('response_cache_for', None)
- if cache_for is not None:
- response.cache_expires = cache_for
- return response
+def derive_view(original_view, permission=None, predicates=(), attr=None,
+ renderer_name=None, wrapper_viewname=None, viewname=None):
+ sm = getSiteManager()
+ return sm.derive_view(original_view, permission=permission,
+ predicates=predicates, attr=attr,
+ renderer_name=renderer_name,
+ wrapper_viewname=wrapper_viewname, viewname=viewname)
+
+def rendered_response(renderer, response, view, context, request,
+ renderer_name):
+ sm = getSiteManager()
+ return sm.rendered_response(renderer, response, view, context, request,
+ renderer_name)
+
+def renderer_from_name(self, path):
+ sm = getSiteManager()
+ return sm.renderer_from_name(path)
def map_view(view, attr=None, renderer_name=None):
- wrapped_view = view
+ sm = getSiteManager()
+ return sm.map_view(view, attr=attr, renderer_name=renderer_name)
+
+def owrap_view(view, viewname, wrapper_viewname):
+ sm = getSiteManager()
+ return sm.owrap_view(view, viewname, wrapper_viewname)
- renderer = None
+def predicate_wrap(view, predicates):
+ sm = getSiteManager()
+ return sm.predicate_wrap(view, predicates)
- if renderer_name is None:
- factory = queryUtility(IRendererFactory) # global default renderer
- if factory is not None:
- renderer_name = ''
- renderer = factory(renderer_name)
- else:
- renderer = renderer_from_name(renderer_name)
-
- if inspect.isclass(view):
- # If the object we've located is a class, turn it into a
- # function that operates like a Zope view (when it's invoked,
- # construct an instance using 'context' and 'request' as
- # position arguments, then immediately invoke the __call__
- # method of the instance with no arguments; __call__ should
- # return an IResponse).
- if requestonly(view, attr):
- # its __init__ accepts only a single request argument,
- # instead of both context and request
- def _bfg_class_requestonly_view(context, request):
- inst = view(request)
- if attr is None:
- response = inst()
- else:
- response = getattr(inst, attr)()
- if renderer is not None:
- response = rendered_response(renderer,
- response, inst,
- context, request,
- renderer_name)
- return response
- wrapped_view = _bfg_class_requestonly_view
- else:
- # its __init__ accepts both context and request
- def _bfg_class_view(context, request):
- inst = view(context, request)
- if attr is None:
- response = inst()
- else:
- response = getattr(inst, attr)()
- if renderer is not None:
- response = rendered_response(renderer,
- response, inst,
- context, request,
- renderer_name)
- return response
- wrapped_view = _bfg_class_view
-
- elif requestonly(view, attr):
- # its __call__ accepts only a single request argument,
- # instead of both context and request
- def _bfg_requestonly_view(context, request):
- if attr is None:
- response = view(request)
- else:
- response = getattr(view, attr)(request)
-
- if renderer is not None:
- response = rendered_response(renderer,
- response, view,
- context, request,
- renderer_name)
- return response
- wrapped_view = _bfg_requestonly_view
-
- elif attr:
- def _bfg_attr_view(context, request):
- response = getattr(view, attr)(context, request)
- if renderer is not None:
- response = rendered_response(renderer,
- response, view,
- context, request,
- renderer_name)
- return response
- wrapped_view = _bfg_attr_view
-
- elif renderer is not None:
- def _rendered_view(context, request):
- response = view(context, request)
- response = rendered_response(renderer,
- response, view,
- context, request,
- renderer_name)
- return response
- wrapped_view = _rendered_view
-
- decorate_view(wrapped_view, view)
- return wrapped_view
+def secure_view(view, permission):
+ sm = getSiteManager()
+ return sm.secure_view(view, permission)
+
+def authdebug_view(self, view, permission):
+ sm = getSiteManager()
+ return sm.authdebug_view(view, permission)
def requestonly(class_or_callable, attr=None):
""" Return true of the class or callable accepts only a request argument,
@@ -678,6 +583,44 @@ def requestonly(class_or_callable, attr=None):
return False
+class MultiView(object):
+ implements(IMultiView)
+
+ def __init__(self, name):
+ self.name = name
+ self.views = []
+
+ def add(self, view, score):
+ self.views.append((score, view))
+ self.views.sort()
+
+ def match(self, context, request):
+ for score, view in self.views:
+ if not hasattr(view, '__predicated__'):
+ return view
+ if view.__predicated__(context, request):
+ return view
+ raise NotFound(self.name)
+
+ def __permitted__(self, context, request):
+ view = self.match(context, request)
+ if hasattr(view, '__permitted__'):
+ return view.__permitted__(context, request)
+ return True
+
+ def __call_permissive__(self, context, request):
+ view = self.match(context, request)
+ view = getattr(view, '__call_permissive__', view)
+ return view(context, request)
+
+ def __call__(self, context, request):
+ for score, view in self.views:
+ try:
+ return view(context, request)
+ except NotFound:
+ continue
+ raise NotFound(self.name)
+
def decorate_view(wrapped_view, original_view):
if wrapped_view is not original_view:
wrapped_view.__module__ = original_view.__module__
@@ -691,7 +634,8 @@ def decorate_view(wrapped_view, original_view):
except AttributeError:
pass
try:
- wrapped_view.__call_permissive__ = original_view.__call_permissive__
+ wrapped_view.__call_permissive__ = \
+ original_view.__call_permissive__
except AttributeError:
pass
try:
@@ -701,134 +645,6 @@ def decorate_view(wrapped_view, original_view):
return True
return False
-def derive_view(original_view, permission=None, predicates=(), attr=None,
- renderer_name=None, wrapper_viewname=None, viewname=None):
- mapped_view = map_view(original_view, attr, renderer_name)
- owrapped_view = owrap_view(mapped_view, viewname, wrapper_viewname)
- secured_view = secure_view(owrapped_view, permission)
- debug_view = authdebug_view(secured_view, permission)
- derived_view = predicate_wrap(debug_view, predicates)
- return derived_view
-
-def owrap_view(view, viewname, wrapper_viewname):
- 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)
- if wrapped_response is None:
- raise ValueError(
- 'No wrapper view named %r found when executing view named %r' %
- (wrapper_viewname, viewname))
- return wrapped_response
- decorate_view(_owrapped_view, view)
- return _owrapped_view
-
-def predicate_wrap(view, predicates):
- if not predicates:
- return view
- def _wrapped(context, request):
- if all((predicate(context, request) for predicate in predicates)):
- return view(context, request)
- raise NotFound('predicate mismatch for view %s' % view)
- def checker(context, request):
- return all((predicate(context, request) for predicate in predicates))
- _wrapped.__predicated__ = checker
- decorate_view(_wrapped, view)
- return _wrapped
-
-def secure_view(view, permission):
- wrapped_view = view
- authn_policy = queryUtility(IAuthenticationPolicy)
- authz_policy = queryUtility(IAuthorizationPolicy)
- if authn_policy and authz_policy and (permission is not None):
- def _secured_view(context, request):
- principals = authn_policy.effective_principals(request)
- if authz_policy.permits(context, principals, permission):
- return view(context, request)
- msg = getattr(request, 'authdebug_message',
- 'Unauthorized: %s failed permission check' % view)
- raise Forbidden(msg)
- _secured_view.__call_permissive__ = view
- def _permitted(context, request):
- principals = authn_policy.effective_principals(request)
- return authz_policy.permits(context, principals, permission)
- _secured_view.__permitted__ = _permitted
- wrapped_view = _secured_view
- decorate_view(wrapped_view, view)
-
- return wrapped_view
-
-def authdebug_view(view, permission):
- wrapped_view = view
- authn_policy = queryUtility(IAuthenticationPolicy)
- authz_policy = queryUtility(IAuthorizationPolicy)
- settings = get_settings()
- debug_authorization = False
- if settings is not None:
- debug_authorization = settings.get('debug_authorization', False)
- if debug_authorization:
- def _authdebug_view(context, request):
- view_name = getattr(request, 'view_name', None)
-
- if authn_policy and authz_policy:
- if permission is None:
- msg = 'Allowed (no permission registered)'
- else:
- principals = authn_policy.effective_principals(request)
- 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))
- logger = queryUtility(ILogger, 'repoze.bfg.debug')
- logger and logger.debug(msg)
- if request is not None:
- request.authdebug_message = msg
- return view(context, request)
-
- wrapped_view = _authdebug_view
- decorate_view(wrapped_view, view)
-
- return wrapped_view
-
-def append_slash_notfound_view(context, request):
- """For behavior like Django's ``APPEND_SLASH=True``, use this view
- as the Not Found view in your application.
-
- When this view is the Not Found view (indicating that no view was
- found), and any routes have been defined in the configuration of
- your application, if the value of ``PATH_INFO`` does not already
- end in a slash, and if the value of ``PATH_INFO`` *plus* a slash
- matches any route's path, do an HTTP redirect to the
- slash-appended PATH_INFO. Note that this will *lose* ``POST``
- data information (turning it into a GET), so you shouldn't rely on
- this to redirect POST requests.
-
- Add the following to your application's ``configure.zcml`` to use
- this view as the Not Found view::
-
- <notfound
- view="repoze.bfg.view.append_slash_notfound_view"/>
- See also :ref:`changing_the_notfound_view`.
-
- .. note:: This function is new as of :mod:`repoze.bfg` version 1.1.
-
- """
- path = request.environ.get('PATH_INFO', '/')
- mapper = queryUtility(IRoutesMapper)
- if mapper is not None and not path.endswith('/'):
- slashpath = path + '/'
- for route in mapper.get_routes():
- if route.match(slashpath) is not None:
- return HTTPFound(location=slashpath)
- return default_view(context, request, '404 Not Found')
+
+