summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt20
-rw-r--r--TODO.txt4
-rw-r--r--docs/glossary.rst7
-rw-r--r--pyramid/config.py306
-rw-r--r--pyramid/tests/test_config.py1337
-rw-r--r--pyramid/tests/test_view.py3
-rw-r--r--pyramid/view.py4
7 files changed, 918 insertions, 763 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 6fe68fb48..4279f950d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -15,12 +15,21 @@ Features
- ``config.add_view`` now accepts a ``decorator`` keyword argument, a callable
which will decorate the view callable before it is added to the registry.
+- add a ``add_view_mapper`` API to Configurator. This API allows you to add
+ a named implementation of a ``pyramid.interfaces.IViewMapperFactory``
+ interface. Its name can be passed as a ``view_mapper`` argument to
+ ``config.add_view``. A view mapper allows objects that are meant to be
+ used as view callables to have an arbitrary argument list and an arbitrary
+ result. This feature will be used by Pyramid extension developers, not by
+ "civilians".
+
+- New constructor argument to Configurator: ``default_view_mapper``. Useful
+ to create systems that have view callables with alternate default calling
+ conventions.
+
- ``config.add_view`` now accepts a ``view_mapper`` keyword argument, which
- should be a class which implements the new
- ``pyramid.interfaces.IViewMapperFactory`` interface. Use of an alternate
- view mapper allows objects that are meant to be used as view callables to
- have an arbitrary argument list and an arbitrary result. This feature will
- be used by Pyramid extension developers, not by "civilians".
+ should either be ``None`` or the name of a view mapper previously
+ registered via ``add_view_mapper``.
- If a handler class provides an ``__action_decorator__`` attribute (usually
a classmethod or staticmethod), use that as the decorator for each view
@@ -90,6 +99,7 @@ Internals
promoted to an API method. If you were overriding this method, you'll now
need to override it as ``unauthenticated_userid`` instead.
+- Remove (non-API) function of config.py named _map_view.
1.0a8 (2010-12-27)
==================
diff --git a/TODO.txt b/TODO.txt
index 5acc923a1..99944874c 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -16,6 +16,10 @@ Must-Have (before 1.0)
- Allow ``decorator=`` and ``view_mapper=`` to be passed via ZCML and the
``view_config`` decorator.
+- Document ``Configurator.add_view_mapper``.
+
+- Consider the ability to defer the choice of view mapper.
+
Should-Have
-----------
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 49d273197..4d0c53d60 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -850,6 +850,11 @@ Glossary
WSGI middleware which can display debuggable traceback information in
the browser when an exception is raised by a Pyramid application. See
http://pypi.python.org/pypi/WebError .
-
+ view mapper
+
+ A view mapper is a class which implements the
+ :class:`pyramid.interfaces.IViewMapperFactory` interface, which performs
+ view argument and return value mapping. This is a plug point for
+ extension builders, not normally used by "civilians".
diff --git a/pyramid/config.py b/pyramid/config.py
index 01d453cd1..c890a0c59 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -246,7 +246,13 @@ class Configurator(object):
``autocommit`` is ``True``. If a conflict is detected a
``ConfigurationConflictError`` will be raised. Calling
:meth:`pyramid.config.Configurator.make_wsgi_app` always implies a final
- commit."""
+ commit.
+
+ If ``default_view_mapper`` is passed, it will be used as the default
+ view mapper factory for view configurations that don't otherwise specify
+ one (see :class:`pyramid.interfaces.IViewMapperFactory`).
+ If a default_view_mapper is not passed, a superdefault view mapper will
+ be used. """
manager = manager # for testing injection
venusian = venusian # for testing injection
@@ -267,6 +273,7 @@ class Configurator(object):
renderer_globals_factory=None,
default_permission=None,
session_factory=None,
+ default_view_mapper=None,
autocommit=False,
):
if package is None:
@@ -292,6 +299,7 @@ class Configurator(object):
renderer_globals_factory=renderer_globals_factory,
default_permission=default_permission,
session_factory=session_factory,
+ default_view_mapper=default_view_mapper,
)
def _set_settings(self, mapping):
@@ -596,9 +604,8 @@ class Configurator(object):
authentication_policy=None, authorization_policy=None,
renderers=DEFAULT_RENDERERS, debug_logger=None,
locale_negotiator=None, request_factory=None,
- renderer_globals_factory=None,
- default_permission=None,
- session_factory=None):
+ renderer_globals_factory=None, default_permission=None,
+ session_factory=None, default_view_mapper=None):
""" 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
@@ -644,7 +651,13 @@ class Configurator(object):
self.set_default_permission(default_permission)
if session_factory is not None:
self.set_session_factory(session_factory)
+ # commit before adding default_view_mapper, as the
+ # default_exceptionresponse_view above requires the superdefault view
+ # mapper
self.commit()
+ if default_view_mapper is not None:
+ self.add_view_mapper(None, default_view_mapper)
+ self.commit()
# getSiteManager is a unit testing dep injection
def hook_zca(self, getSiteManager=None):
@@ -1140,11 +1153,11 @@ class Configurator(object):
decorator
A function which will be used to decorate the registered
- :term:`view callable`. The decorator function will be
- called with the view callable as a single argument, and it
- must return a replacement view callable which accepts the
- same arguments and returns the same type of values as the
- original function.
+ :term:`view callable`. The decorator function will be called with
+ the view callable as a single argument. The view callable it is
+ passed will accept ``(context, request)`. The decorator must
+ return a replacement view callable which also accepts ``(context,
+ request)``.
Predicate Arguments
@@ -1285,14 +1298,12 @@ class Configurator(object):
view_mapper
- A class implementing the
- :class:`pyramid.interfaces.IViewMapperFactory` interface, which
- performs view argument and response mapping. By default it is
- ``None``, which indicates that the view should use the default view
- mapper. This plug-point is useful for Pyramid extension
- developers, but it's not very useful for 'civilians' who are
- just developing stock Pyramid applications. Pay no attention to
- the man behind the curtain.
+ The name of a previously registered :term:`view mapper` or
+ ``None``. By default it is ``None``, which indicates that the view
+ should use the default view mapper. This plug-point is useful for
+ Pyramid extension developers, but it's not very useful for
+ 'civilians' who are just developing stock Pyramid applications.
+ Pay no attention to the man behind the curtain.
"""
view = self.maybe_dotted(view)
@@ -1369,19 +1380,20 @@ class Configurator(object):
# intent: will be None if no default permission is registered
permission = self.registry.queryUtility(IDefaultPermission)
- # NO_PERMISSION_REQUIRED handled by _secure_view
- derived_view = ViewDeriver(registry=self.registry,
- permission=permission,
- predicates=predicates,
- attr=attr,
- renderer=renderer,
- wrapper_viewname=wrapper,
- viewname=name,
- accept=accept,
- order=order,
- phash=phash,
- decorator=decorator,
- view_mapper=view_mapper)(view)
+ # __no_permission_required__ handled by _secure_view
+ deriver = ViewDeriver(registry=self.registry,
+ permission=permission,
+ predicates=predicates,
+ attr=attr,
+ renderer=renderer,
+ wrapper_viewname=wrapper,
+ viewname=name,
+ accept=accept,
+ order=order,
+ phash=phash,
+ decorator=decorator,
+ view_mapper=view_mapper)
+ derived_view = deriver(view)
registered = self.registry.adapters.registered
@@ -2163,6 +2175,36 @@ class Configurator(object):
self.action(IDefaultPermission, None)
@action_method
+ def add_view_mapper(self, name, mapper):
+ """
+ Adding a :term:`view mapper` makes it possible to make use of
+ :term:`view callable` objects which implement a different call
+ signature than the ones described in the :app:`Pyramid`
+ documentation. This is an advanced feature, not usually consumed by
+ 'civilians'.
+
+ ``name`` must be a string or ``None``. If ``name`` is a string, the
+ view mapper will be registered under the specified name for
+ consumption by extensions. If ``name`` is ``None``, the provided
+ mapper will become the *default* view mapper to be used by all
+ subsequent :term:`view configuration` registrations, as if you had
+ passed a ``default_view_mapper`` argument to the
+ :class:`pyramid.config.Configurator` constructor.
+
+ The ``mapper`` should argument be an object implementing
+ :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted
+ Python name` to such an object.
+
+ See also :ref:`using_an_alternate_view_mapper`.
+ """
+ if mapper is not None:
+ mapper = self.maybe_dotted(mapper)
+ if name is None:
+ name = ''
+ self.registry.registerUtility(mapper, IViewMapperFactory, name=name)
+ self.action((IViewMapperFactory, name), None)
+
+ @action_method
def set_session_factory(self, session_factory):
"""
Configure the application with a :term:`session factory`. If
@@ -2738,19 +2780,29 @@ class ViewDeriver(object):
self.logger = self.registry.queryUtility(IDebugLogger)
def __call__(self, view):
- mapper = self.kw.get('view_mapper')
- if mapper is None:
- mapper = DefaultViewMapper
- view = mapper(**self.kw)(view)
return self.attr_wrapped_view(
self.predicated_view(
self.authdebug_view(
self.secured_view(
- self.owrap_view(
- view)))))
+ self.owrapped_view(
+ self.decorated_view(
+ self.rendered_view(
+ self.mapped_view(view))))))))
@wraps_view
- def owrap_view(self, view):
+ def mapped_view(self, view):
+ mapper_name = self.kw.get('view_mapper')
+ mapper = self.registry.queryUtility(IViewMapperFactory,
+ name=mapper_name)
+
+ if mapper is None:
+ mapper = DefaultViewMapper
+
+ mapped_view = mapper(**self.kw)(view)
+ return mapped_view
+
+ @wraps_view
+ def owrapped_view(self, view):
wrapper_viewname = self.kw.get('wrapper_viewname')
viewname = self.kw.get('viewname')
if not wrapper_viewname:
@@ -2864,29 +2916,53 @@ class ViewDeriver(object):
attr_view.__phash__ = phash
return attr_view
+ @wraps_view
+ def rendered_view(self, view):
+ wrapped_view = view
+ renderer = self.kw.get('renderer')
+ if renderer is None:
+ return view
+
+ def _rendered_view(context, request):
+ response = wrapped_view(context, request)
+ if not is_response(response):
+ attrs = getattr(request, '__dict__', {})
+ if '__view__' in attrs:
+ view_inst = attrs.pop('__view__')
+ else:
+ view_inst = getattr(wrapped_view, '__original_view__',
+ wrapped_view)
+ return renderer.render_view(request, response, view_inst,
+ context)
+ return response
+
+ return _rendered_view
+
+ @wraps_view
+ def decorated_view(self, view):
+ decorator = self.kw.get('decorator')
+ if decorator is None:
+ return view
+ return decorator(view)
+
class DefaultViewMapper(object):
implements(IViewMapperFactory)
def __init__(self, **kw):
- self.renderer = kw.get('renderer')
self.attr = kw.get('attr')
- self.decorator = kw.get('decorator')
def __call__(self, view):
- decorator = self.decorator
if inspect.isclass(view):
- view = preserve_view_attrs(view, self.map_class(view))
+ view = self.map_class(view)
else:
- view = preserve_view_attrs(view, self.map_nonclass(view))
- if decorator is not None:
- view = preserve_view_attrs(view, decorator(view))
+ view = self.map_nonclass(view)
return view
def map_class(self, view):
- ronly = self.requestonly(view)
+ ronly = requestonly(view, self.attr)
if ronly:
- mapped_view = self._map_class_requestonly(view)
+ mapped_view = self.map_class_requestonly(view)
else:
- mapped_view = self._map_class_native(view)
+ mapped_view = self.map_class_native(view)
return mapped_view
def map_nonclass(self, view):
@@ -2894,47 +2970,41 @@ class DefaultViewMapper(object):
# view unless it actually requires wrapping (to avoid function call
# overhead).
mapped_view = view
- ronly = self.requestonly(view)
+ ronly = requestonly(view, self.attr)
if ronly:
- mapped_view = self._map_nonclass_requestonly(view)
+ mapped_view = self.map_nonclass_requestonly(view)
elif self.attr:
- mapped_view = self._map_nonclass_attr(view)
- elif self.renderer is not None:
- mapped_view = self._map_nonclass_rendered(view)
+ mapped_view = self.map_nonclass_attr(view)
return mapped_view
- def _map_class_requestonly(self, view):
+ 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
if attr is None:
response = inst()
else:
response = getattr(inst, attr)()
- if self.renderer is not None and not is_response(response):
- response = self.renderer.render_view(request, response, view,
- context)
return response
return _class_requestonly_view
- def _map_class_native(self, 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
if attr is None:
response = inst()
else:
response = getattr(inst, attr)()
- if self.renderer is not None and not is_response(response):
- response = self.renderer.render_view(request, response, view,
- context)
return response
return _class_view
- def _map_nonclass_requestonly(self, view):
+ def map_nonclass_requestonly(self, view):
# its a function that has a __call__ which accepts only a single
# request argument
attr = self.attr
@@ -2943,86 +3013,58 @@ class DefaultViewMapper(object):
response = view(request)
else:
response = getattr(view, attr)(request)
- if self.renderer is not None and not is_response(response):
- response = self.renderer.render_view(request, response, view,
- context)
return response
return _requestonly_view
- def _map_nonclass_attr(self, view):
+ def map_nonclass_attr(self, view):
# its a function that has a __call__ which accepts both context and
# request, but still has an attr
- attr = self.attr
def _attr_view(context, request):
- response = getattr(view, attr)(context, request)
- if self.renderer is not None and not is_response(response):
- response = self.renderer.render_view(request, response, view,
- context)
+ response = getattr(view, self.attr)(context, request)
return response
return _attr_view
- def _map_nonclass_rendered(self, view):
- # it's a function that has a __call__ that accepts both context and
- # request, but requires rendering
- def _rendered_view(context, request):
- response = view(context, request)
- if self.renderer is not None and not is_response(response):
- response = self.renderer.render_view(request, response, view,
- context)
- return response
- return _rendered_view
-
- def requestonly(self, view):
- attr = self.attr
- if attr is None:
- attr = '__call__'
- if inspect.isfunction(view):
- fn = view
- elif inspect.isclass(view):
- try:
- fn = view.__init__
- except AttributeError:
- return False
- else:
- try:
- fn = getattr(view, attr)
- except AttributeError:
- return False
-
+def requestonly(view, attr=None):
+ if attr is None:
+ attr = '__call__'
+ if inspect.isfunction(view):
+ fn = view
+ elif inspect.isclass(view):
try:
- argspec = inspect.getargspec(fn)
- except TypeError:
+ fn = view.__init__
+ except AttributeError:
return False
-
- args = argspec[0]
- defaults = argspec[3]
-
- if hasattr(fn, 'im_func'):
- # it's an instance method
- if not args:
- return False
- args = args[1:]
- if not args:
+ else:
+ try:
+ fn = getattr(view, attr)
+ except AttributeError:
return False
- if len(args) == 1:
- return True
+ try:
+ argspec = inspect.getargspec(fn)
+ except TypeError:
+ return False
- elif args[0] == 'request':
- if len(args) - len(defaults) == 1:
- return True
+ args = argspec[0]
+ defaults = argspec[3]
+ if hasattr(fn, 'im_func'):
+ # it's an instance method
+ if not args:
+ return False
+ args = args[1:]
+ if not args:
return False
+ if len(args) == 1:
+ return True
-def isexception(o):
- if IInterface.providedBy(o):
- if IException.isEqualOrExtendedBy(o):
+ elif args[0] == 'request':
+ if len(args) - len(defaults) == 1:
return True
- return (
- isinstance(o, Exception) or
- (inspect.isclass(o) and (issubclass(o, Exception)))
- )
+
+ return False
+
class ActionPredicate(object):
action_name = 'action'
@@ -3069,20 +3111,18 @@ def translator(msg):
localizer = get_localizer(request)
return localizer.translate(msg)
-# b/c
-def _map_view(view, registry, attr=None, renderer=None):
- return DefaultViewMapper(registry=registry, attr=attr,
- renderer=renderer)(view)
-
-# b/c
-def requestonly(view, attr=None):
- """ Return true of the class or callable accepts only a request argument,
- as opposed to something that accepts context, request """
- return DefaultViewMapper(attr=attr).requestonly(view)
-
def is_response(ob):
if ( hasattr(ob, 'app_iter') and hasattr(ob, 'headerlist') and
hasattr(ob, 'status') ):
return True
return False
+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)))
+ )
+
diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py
index 1760d119a..ceb62612f 100644
--- a/pyramid/tests/test_config.py
+++ b/pyramid/tests/test_config.py
@@ -63,27 +63,11 @@ class ConfiguratorTests(unittest.TestCase):
config.registry.registerHandler(subscriber, (event_iface,))
return L
- def _registerLogger(self, config):
- from pyramid.interfaces import IDebugLogger
- logger = DummyLogger()
- config.registry.registerUtility(logger, IDebugLogger)
- return logger
-
def _makeRequest(self, config):
request = DummyRequest()
request.registry = config.registry
return request
- def _registerSecurityPolicy(self, config, permissive):
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- policy = DummySecurityPolicy(permissive)
- config.registry.registerUtility(policy, IAuthenticationPolicy)
- config.registry.registerUtility(policy, IAuthorizationPolicy)
-
- def _registerSettings(self, config, **settings):
- config.registry.settings = settings
-
def test_ctor_no_registry(self):
import sys
from pyramid.interfaces import ISettings
@@ -196,6 +180,13 @@ class ConfiguratorTests(unittest.TestCase):
config = self._makeOne(session_factory='factory')
self.assertEqual(config.registry.getUtility(ISessionFactory), 'factory')
+ def test_ctor_default_view_mapper(self):
+ from pyramid.interfaces import IViewMapperFactory
+ mapper = object()
+ config = self._makeOne(default_view_mapper=mapper)
+ self.assertEqual(config.registry.getUtility(IViewMapperFactory),
+ mapper)
+
def test_with_package_module(self):
from pyramid.tests import test_configuration
import pyramid.tests
@@ -790,8 +781,10 @@ class ConfiguratorTests(unittest.TestCase):
config = self._makeOne(autocommit=True)
config.add_view(view=view)
wrapper = self._getViewCallable(config)
- result = wrapper(None, None)
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
self.assertEqual(result, 'OK')
+ self.assertEqual(request.__view__.__class__, view)
def test_add_view_as_oldstyle_class_requestonly(self):
class view:
@@ -803,8 +796,11 @@ class ConfiguratorTests(unittest.TestCase):
config = self._makeOne(autocommit=True)
config.add_view(view=view)
wrapper = self._getViewCallable(config)
- result = wrapper(None, None)
+
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
self.assertEqual(result, 'OK')
+ self.assertEqual(request.__view__.__class__, view)
def test_add_view_context_as_class(self):
from zope.interface import implementedBy
@@ -1427,8 +1423,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(result.settings, settings)
def test_add_view_with_default_renderer(self):
- import pyramid.tests
- from pyramid.interfaces import ISettings
class view(object):
def __init__(self, context, request):
self.request = request
@@ -2340,7 +2334,8 @@ class ConfiguratorTests(unittest.TestCase):
request_type = self._getRouteRequestIface(config, 'name')
wrapper = self._getViewCallable(config, None, request_type)
self._assertRoute(config, 'name', 'path')
- self.assertEqual(wrapper(None, None), 'OK')
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(None, request), 'OK')
def test_add_route_with_view_renderer_alias(self):
config = self._makeOne(autocommit=True)
@@ -2437,6 +2432,52 @@ class ConfiguratorTests(unittest.TestCase):
else: # pragma: no cover
raise AssertionError
+ def test_derive_view_function(self):
+ def view(request):
+ return 'OK'
+ config = self._makeOne()
+ result = config.derive_view(view)
+ self.failIf(result is view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_derive_view_dottedname(self):
+ config = self._makeOne()
+ result = config.derive_view(
+ 'pyramid.tests.test_config.dummy_view')
+ self.failIf(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)
+ def view(request):
+ return 'OK'
+ result = config.derive_view(view)
+ self.failIf(result is view)
+ self.assertEqual(result(None, None).body, 'moo')
+
+ def test_derive_view_with_default_renderer_with_explicit_renderer(self):
+ class moo(object): pass
+ class foo(object):
+ def __init__(self, view):
+ pass
+ def __call__(self, *arg, **kw):
+ return 'foo'
+ def view(request):
+ return 'OK'
+ config = self._makeOne()
+ config.add_renderer(None, moo)
+ config.add_renderer('foo', foo)
+ result = config.derive_view(view, renderer='foo')
+ self.failIf(result is view)
+ request = self._makeRequest(config)
+ self.assertEqual(result(None, request).body, 'foo')
+
def test__override_not_yet_registered(self):
from pyramid.interfaces import IPackageOverrides
package = DummyPackage('package')
@@ -2633,6 +2674,22 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(config.registry.getUtility(IDefaultPermission),
'view')
+ def test_add_view_mapper(self):
+ from pyramid.interfaces import IViewMapperFactory
+ config = self._makeOne(autocommit=True)
+ mapper = object()
+ config.add_view_mapper('mapper', mapper)
+ result = config.registry.getUtility(IViewMapperFactory, name='mapper')
+ self.assertEqual(result, mapper)
+
+ def test_add_view_mapper_dottedname(self):
+ from pyramid.interfaces import IViewMapperFactory
+ config = self._makeOne(autocommit=True)
+ config.add_view_mapper('mapper', 'pyramid.tests.test_config')
+ result = config.registry.getUtility(IViewMapperFactory, name='mapper')
+ from pyramid.tests import test_config
+ self.assertEqual(result, test_config)
+
def test_set_session_factory(self):
from pyramid.interfaces import ISessionFactory
config = self._makeOne(autocommit=True)
@@ -2680,404 +2737,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(config.registry.getUtility(ITranslationDirectories),
[locale])
- def test_derive_view_function(self):
- def view(request):
- return 'OK'
- config = self._makeOne()
- result = config.derive_view(view)
- self.failIf(result is view)
- self.assertEqual(result(None, None), 'OK')
-
- def test_derive_view_dottedname(self):
- config = self._makeOne()
- result = config.derive_view(
- 'pyramid.tests.test_config.dummy_view')
- self.failIf(result is dummy_view)
- self.assertEqual(result(None, None), 'OK')
-
- def test_derive_view_with_renderer(self):
- def view(request):
- return 'OK'
- config = self._makeOne(autocommit=True)
- class moo(object):
- def __init__(self, *arg, **kw):
- pass
- def __call__(self, *arg, **kw):
- return 'moo'
- config.add_renderer('moo', moo)
- result = config.derive_view(view, renderer='moo')
- self.failIf(result is view)
- self.assertEqual(result(None, None).body, 'moo')
-
- def test_derive_view_with_default_renderer_no_explicit_renderer(self):
- def view(request):
- return 'OK'
- config = self._makeOne(autocommit=True)
- class moo(object):
- def __init__(self, *arg, **kw):
- pass
- def __call__(self, *arg, **kw):
- return 'moo'
- config.add_renderer(None, moo)
- result = config.derive_view(view)
- self.failIf(result is view)
- self.assertEqual(result(None, None).body, 'moo')
-
- def test_derive_view_with_default_renderer_with_explicit_renderer(self):
- def view(request):
- return 'OK'
- config = self._makeOne(autocommit=True)
- class moo(object): pass
- class foo(object):
- def __init__(self, *arg, **kw):
- pass
- def __call__(self, *arg, **kw):
- return 'foo'
- config.add_renderer(None, moo)
- config.add_renderer('foo', foo)
- result = config.derive_view(view, renderer='foo')
- self.failIf(result is view)
- self.assertEqual(result(None, None).body, 'foo')
-
- def test_derive_view_class_without_attr(self):
- class View(object):
- def __init__(self, request):
- pass
- def __call__(self):
- return 'OK'
- config = self._makeOne()
- result = config.derive_view(View)
- self.assertEqual(result(None, None), 'OK')
-
- def test_derive_view_class_with_attr(self):
- class View(object):
- def __init__(self, request):
- pass
- def another(self):
- return 'OK'
- config = self._makeOne()
- result = config.derive_view(View, attr='another')
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_function_context_and_request(self):
- def view(context, request):
- return 'OK'
- config = self._makeOne()
- result = config._derive_view(view)
- self.failUnless(result is view)
- self.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(view(None, None), 'OK')
-
- def test__derive_view_as_function_requestonly(self):
- def view(request):
- return 'OK'
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_newstyle_class_context_and_request(self):
- class view(object):
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_newstyle_class_requestonly(self):
- class view(object):
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_oldstyle_class_context_and_request(self):
- class view:
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_oldstyle_class_requestonly(self):
- class view:
- def __init__(self, context, request):
- pass
- def __call__(self):
- return 'OK'
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_instance_context_and_request(self):
- class View:
- def __call__(self, context, request):
- return 'OK'
- view = View()
- config = self._makeOne()
- result = config._derive_view(view)
- self.failUnless(result is view)
- self.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_as_instance_requestonly(self):
- class View:
- def __call__(self, request):
- return 'OK'
- view = View()
- config = self._makeOne()
- result = config._derive_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.failIf(hasattr(result, '__call_permissive__'))
- self.assertEqual(result(None, None), 'OK')
-
- def test__derive_view_with_debug_authorization_no_authpol(self):
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config,
- debug_authorization=True, reload_templates=True)
- logger = self._registerLogger(config)
- result = config._derive_view(view, permission='view')
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.failIf(hasattr(result, '__call_permissive__'))
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- self.assertEqual(result(None, request), 'OK')
- 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)")
-
- def test__derive_view_with_debug_authorization_no_permission(self):
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config,
- debug_authorization=True, reload_templates=True)
- self._registerSecurityPolicy(config, True)
- logger = self._registerLogger(config)
- result = config._derive_view(view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.failIf(hasattr(result, '__call_permissive__'))
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- self.assertEqual(result(None, request), 'OK')
- 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)")
-
- def test__derive_view_debug_auth_permission_authpol_permitted(self):
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config, debug_authorization=True,
- reload_templates=True)
- logger = self._registerLogger(config)
- self._registerSecurityPolicy(config, True)
- result = config._derive_view(view, permission='view')
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result.__call_permissive__, view)
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- self.assertEqual(result(None, request), 'OK')
- self.assertEqual(len(logger.messages), 1)
- self.assertEqual(logger.messages[0],
- "debug_authorization of url url (view name "
- "'view_name' against context None): True")
-
- def test__derive_view_debug_auth_permission_authpol_denied(self):
- from pyramid.exceptions import Forbidden
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config,
- debug_authorization=True, reload_templates=True)
- logger = self._registerLogger(config)
- self._registerSecurityPolicy(config, False)
- result = config._derive_view(view, permission='view')
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- self.assertEqual(result.__call_permissive__, view)
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- self.assertRaises(Forbidden, 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")
-
- def test__derive_view_debug_auth_permission_authpol_denied2(self):
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config,
- debug_authorization=True, reload_templates=True)
- self._registerLogger(config)
- self._registerSecurityPolicy(config, False)
- result = config._derive_view(view, permission='view')
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- permitted = result.__permitted__(None, None)
- self.assertEqual(permitted, False)
-
- def test__derive_view_debug_auth_permission_authpol_overridden(self):
- view = lambda *arg: 'OK'
- config = self._makeOne()
- self._registerSettings(config,
- debug_authorization=True, reload_templates=True)
- logger = self._registerLogger(config)
- self._registerSecurityPolicy(config, False)
- result = 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__)
- self.failIf(hasattr(result, '__call_permissive__'))
- request = self._makeRequest(config)
- request.view_name = 'view_name'
- request.url = 'url'
- self.assertEqual(result(None, request), 'OK')
- self.assertEqual(len(logger.messages), 1)
- self.assertEqual(logger.messages[0],
- "debug_authorization of url url (view name "
- "'view_name' against context None): False")
-
- def test__derive_view_with_predicates_all(self):
- view = lambda *arg: 'OK'
- predicates = []
- def predicate1(context, request):
- predicates.append(True)
- return True
- def predicate2(context, request):
- predicates.append(True)
- return True
- config = self._makeOne()
- result = config._derive_view(view, predicates=[predicate1, predicate2])
- request = self._makeRequest(config)
- request.method = 'POST'
- next = result(None, None)
- self.assertEqual(next, 'OK')
- self.assertEqual(predicates, [True, True])
-
- def test__derive_view_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
- config = self._makeOne()
- result = config._derive_view(view, predicates=[predicate1, predicate2])
- request = self._makeRequest(config)
- request.method = 'POST'
- next = result.__predicated__(None, None)
- self.assertEqual(next, True)
- self.assertEqual(predicates, [True, True])
-
- def test__derive_view_with_predicates_notall(self):
- from pyramid.exceptions import NotFound
- view = lambda *arg: 'OK'
- predicates = []
- def predicate1(context, request):
- predicates.append(True)
- return True
- def predicate2(context, request):
- predicates.append(True)
- return False
- config = self._makeOne()
- result = config._derive_view(view, predicates=[predicate1, predicate2])
- request = self._makeRequest(config)
- request.method = 'POST'
- self.assertRaises(NotFound, result, None, None)
- self.assertEqual(predicates, [True, True])
-
- def test__derive_view_with_wrapper_viewname(self):
- from webob 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, inner_view)
- return Response('outer ' + request.wrapped_body)
- config = self._makeOne()
- config.registry.registerAdapter(
- outer_view, (IViewClassifier, None, None), IView, 'owrap')
- result = config._derive_view(inner_view, viewname='inner',
- wrapper_viewname='owrap')
- self.failIf(result is inner_view)
- self.assertEqual(inner_view.__module__, result.__module__)
- self.assertEqual(inner_view.__doc__, result.__doc__)
- request = self._makeRequest(config)
- request.registry = config.registry
- response = result(None, request)
- self.assertEqual(response.body, 'outer OK')
-
- def test__derive_view_with_wrapper_viewname_notfound(self):
- from webob import Response
- inner_response = Response('OK')
- def inner_view(context, request):
- return inner_response
- config = self._makeOne()
- request = self._makeRequest(config)
- request.registry = config.registry
- wrapped = config._derive_view(
- inner_view, viewname='inner', wrapper_viewname='owrap')
- self.assertRaises(ValueError, wrapped, None, request)
-
def test_override_asset_samename(self):
from pyramid.exceptions import ConfigurationError
config = self._makeOne()
@@ -3557,334 +3216,755 @@ class ConfiguratorTests(unittest.TestCase):
for confinst in conflict:
yield confinst[2]
-class Test__map_view(unittest.TestCase):
+class TestViewDeriver(unittest.TestCase):
def setUp(self):
- from pyramid.registry import Registry
- self.registry = Registry()
- testing.setUp(registry=self.registry)
+ self.config = testing.setUp()
def tearDown(self):
- del self.registry
- testing.tearDown()
-
- def _registerRenderer(self, typ='.txt'):
- from pyramid.interfaces import IRendererFactory
- from pyramid.interfaces import ITemplateRenderer
- from pyramid.renderers import RendererHelper
- from zope.interface import implements
- class DummyRenderer:
- implements(ITemplateRenderer)
- def __init__(self, path):
- self.__class__.path = path
- def __call__(self, *arg):
- return 'Hello!'
- self.registry.registerUtility(DummyRenderer, IRendererFactory, name=typ)
- renderer = RendererHelper(name='abc' + typ, registry=self.registry)
- return renderer
-
+ self.config = None
+
+ def _makeOne(self, **kw):
+ kw['registry'] = self.config.registry
+ from pyramid.config import ViewDeriver
+ return ViewDeriver(**kw)
+
def _makeRequest(self):
request = DummyRequest()
- request.registry = self.registry
+ request.registry = self.config.registry
return request
- def _callFUT(self, view, **kw):
- from pyramid.config import _map_view
- return _map_view(view, self.registry, **kw)
+ def _registerLogger(self):
+ from pyramid.interfaces import IDebugLogger
+ logger = DummyLogger()
+ self.config.registry.registerUtility(logger, IDebugLogger)
+ return logger
- def test__map_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 _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)
- def test__map_view_as_function_with_attr(self):
- def view(context, request):
- """ """
- result = self._callFUT(view, attr='__name__')
+ def test_requestonly_function(self):
+ def view(request):
+ return 'OK'
+ deriver = self._makeOne()
+ result = deriver(view)
self.failIf(result is view)
- self.assertRaises(TypeError, result, None, None)
+ self.assertEqual(result(None, None), 'OK')
- def test__map_view_as_function_with_attr_and_renderer(self):
- renderer = self._registerRenderer()
- view = lambda *arg: 'OK'
- result = self._callFUT(view, attr='__name__', renderer=renderer)
+ def test_requestonly_function_with_renderer(self):
+ class moo(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, 'OK')
+ self.assertEqual(view_inst, view)
+ self.assertEqual(ctx, context)
+ return 'moo'
+ def view(request):
+ return 'OK'
+ deriver = self._makeOne(renderer=moo())
+ result = deriver(view)
self.failIf(result is view)
- self.assertRaises(TypeError, result, None, None)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), 'moo')
- def test__map_view_as_function_requestonly(self):
+ def test_requestonly_function_with_renderer_request_has_view(self):
+ class moo(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, 'OK')
+ self.assertEqual(view_inst, 'view')
+ self.assertEqual(ctx, context)
+ return 'moo'
def view(request):
return 'OK'
- result = self._callFUT(view)
+ deriver = self._makeOne(renderer=moo())
+ result = deriver(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')
+ request = self._makeRequest()
+ request.__view__ = 'view'
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), 'moo')
+ self.failIf(hasattr(request, '__view__'))
- def test__map_view_as_function_requestonly_with_attr(self):
+ def test_class_without_attr(self):
+ class View(object):
+ def __init__(self, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ deriver = self._makeOne()
+ result = deriver(View)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, View)
+
+ def test_class_with_attr(self):
+ class View(object):
+ def __init__(self, request):
+ pass
+ def another(self):
+ return 'OK'
+ deriver = self._makeOne(attr='another')
+ result = deriver(View)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, View)
+
+ def test_as_function_context_and_request(self):
+ def view(context, request):
+ return 'OK'
+ deriver = self._makeOne()
+ result = deriver(view)
+ self.failUnless(result is view)
+ self.failIf(hasattr(result, '__call_permissive__'))
+ self.assertEqual(view(None, None), 'OK')
+
+ def test_as_function_requestonly(self):
def view(request):
- """ """
- result = self._callFUT(view, attr='__name__')
+ return 'OK'
+ deriver = self._makeOne()
+ result = deriver(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.assertRaises(TypeError, result, None, None)
+ self.failIf(hasattr(result, '__call_permissive__'))
+ self.assertEqual(result(None, None), 'OK')
- def test__map_view_as_newstyle_class_context_and_request(self):
+ def test_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)
+ deriver = self._makeOne()
+ result = deriver(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')
+ self.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, view)
- def test__map_view_as_newstyle_class_context_and_request_with_attr(self):
+ def test_as_newstyle_class_requestonly(self):
class view(object):
def __init__(self, context, request):
pass
- def index(self):
+ def __call__(self):
return 'OK'
- result = self._callFUT(view, attr='index')
+ deriver = self._makeOne()
+ result = deriver(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')
+ self.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, view)
- def test__map_view_as_newstyle_class_context_and_request_attr_and_renderer(
- self):
- renderer = self._registerRenderer()
- class view(object):
+ def test_as_oldstyle_class_context_and_request(self):
+ class view:
def __init__(self, context, request):
pass
- def index(self):
- return {'a':'1'}
- result = self._callFUT(view, attr='index', renderer=renderer)
+ def __call__(self):
+ return 'OK'
+ deriver = self._makeOne()
+ result = deriver(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.failIf(hasattr(result, '__call_permissive__'))
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, view)
- def test__map_view_as_newstyle_class_requestonly(self):
- class view(object):
- def __init__(self, request):
+ def test_as_oldstyle_class_requestonly(self):
+ class view:
+ def __init__(self, context, request):
pass
def __call__(self):
return 'OK'
- result = self._callFUT(view)
+ deriver = self._makeOne()
+ result = deriver(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.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(request.__view__.__class__, view)
+
+ def test_as_instance_context_and_request(self):
+ class View:
+ def __call__(self, context, request):
+ return 'OK'
+ view = View()
+ deriver = self._makeOne()
+ result = deriver(view)
+ self.failUnless(result is view)
+ self.failIf(hasattr(result, '__call_permissive__'))
self.assertEqual(result(None, None), 'OK')
- def test__map_view_as_newstyle_class_requestonly_with_attr(self):
- class view(object):
- def __init__(self, request):
- pass
- def index(self):
+ def test_as_instance_requestonly(self):
+ class View:
+ def __call__(self, request):
return 'OK'
- result = self._callFUT(view, attr='index')
+ view = View()
+ deriver = self._makeOne()
+ result = deriver(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.failUnless('instance' in result.__name__)
+ self.failIf(hasattr(result, '__call_permissive__'))
self.assertEqual(result(None, None), 'OK')
- def test__map_view_as_newstyle_class_requestonly_attr_and_renderer(self):
- renderer = self._registerRenderer()
- class view(object):
+ def test_with_debug_authorization_no_authpol(self):
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ logger = self._registerLogger()
+ deriver = self._makeOne(permission='view')
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ self.assertEqual(result(None, request), 'OK')
+ 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)")
+
+ def test_with_debug_authorization_no_permission(self):
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ self._registerSecurityPolicy(True)
+ logger = self._registerLogger()
+ deriver = self._makeOne()
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ self.assertEqual(result(None, request), 'OK')
+ 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)")
+
+ def test_debug_auth_permission_authpol_permitted(self):
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ logger = self._registerLogger()
+ self._registerSecurityPolicy(True)
+ deriver = self._makeOne(permission='view')
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result.__call_permissive__, view)
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(len(logger.messages), 1)
+ self.assertEqual(logger.messages[0],
+ "debug_authorization of url url (view name "
+ "'view_name' against context None): True")
+
+ def test_debug_auth_permission_authpol_denied(self):
+ from pyramid.exceptions import Forbidden
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ logger = self._registerLogger()
+ self._registerSecurityPolicy(False)
+ deriver = self._makeOne(permission='view')
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.assertEqual(result.__call_permissive__, view)
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ self.assertRaises(Forbidden, 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")
+
+ def test_debug_auth_permission_authpol_denied2(self):
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ self._registerLogger()
+ self._registerSecurityPolicy(False)
+ deriver = self._makeOne(permission='view')
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ permitted = result.__permitted__(None, None)
+ self.assertEqual(permitted, False)
+
+ def test_debug_auth_permission_authpol_overridden(self):
+ view = lambda *arg: 'OK'
+ self.config.registry.settings = dict(
+ debug_authorization=True, reload_templates=True)
+ logger = self._registerLogger()
+ self._registerSecurityPolicy(False)
+ deriver = self._makeOne(permission='__no_permission_required__')
+ result = deriver(view)
+ self.assertEqual(view.__module__, result.__module__)
+ self.assertEqual(view.__doc__, result.__doc__)
+ self.assertEqual(view.__name__, result.__name__)
+ self.failIf(hasattr(result, '__call_permissive__'))
+ request = self._makeRequest()
+ request.view_name = 'view_name'
+ request.url = 'url'
+ self.assertEqual(result(None, request), 'OK')
+ self.assertEqual(len(logger.messages), 1)
+ self.assertEqual(logger.messages[0],
+ "debug_authorization of url url (view name "
+ "'view_name' against context None): False")
+
+ def test_with_predicates_all(self):
+ view = lambda *arg: 'OK'
+ predicates = []
+ def predicate1(context, request):
+ predicates.append(True)
+ return True
+ def predicate2(context, request):
+ predicates.append(True)
+ return True
+ deriver = self._makeOne(predicates=[predicate1, predicate2])
+ result = deriver(view)
+ request = self._makeRequest()
+ request.method = 'POST'
+ next = result(None, None)
+ self.assertEqual(next, 'OK')
+ self.assertEqual(predicates, [True, True])
+
+ 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
+ deriver = self._makeOne(predicates=[predicate1, predicate2])
+ result = deriver(view)
+ request = self._makeRequest()
+ request.method = 'POST'
+ next = result.__predicated__(None, None)
+ self.assertEqual(next, True)
+ self.assertEqual(predicates, [True, True])
+
+ def test_with_predicates_notall(self):
+ from pyramid.exceptions import NotFound
+ view = lambda *arg: 'OK'
+ predicates = []
+ def predicate1(context, request):
+ predicates.append(True)
+ return True
+ def predicate2(context, request):
+ predicates.append(True)
+ return False
+ deriver = self._makeOne(predicates=[predicate1, predicate2])
+ result = deriver(view)
+ request = self._makeRequest()
+ request.method = 'POST'
+ self.assertRaises(NotFound, result, None, None)
+ self.assertEqual(predicates, [True, True])
+
+ def test_with_wrapper_viewname(self):
+ from webob 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, inner_view)
+ return Response('outer ' + request.wrapped_body)
+ self.config.registry.registerAdapter(
+ outer_view, (IViewClassifier, None, None), IView, 'owrap')
+ deriver = self._makeOne(viewname='inner',
+ wrapper_viewname='owrap')
+ result = deriver(inner_view)
+ self.failIf(result is inner_view)
+ self.assertEqual(inner_view.__module__, result.__module__)
+ self.assertEqual(inner_view.__doc__, result.__doc__)
+ request = self._makeRequest()
+ response = result(None, request)
+ self.assertEqual(response.body, 'outer OK')
+
+ def test_with_wrapper_viewname_notfound(self):
+ from webob import Response
+ inner_response = Response('OK')
+ def inner_view(context, request):
+ return inner_response
+ deriver = self._makeOne(viewname='inner', wrapper_viewname='owrap')
+ wrapped = deriver(inner_view)
+ request = self._makeRequest()
+ self.assertRaises(ValueError, wrapped, None, request)
+
+ def test_as_newstyle_class_context_and_request_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst.__class__, View)
+ self.assertEqual(ctx, context)
+ return resp
+ class View(object):
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ result = deriver(View)
+ self.failIf(result is View)
+ self.assertEqual(result.__module__, View.__module__)
+ self.assertEqual(result.__doc__, View.__doc__)
+ self.assertEqual(result.__name__, View.__name__)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
+
+ def test_as_newstyle_class_requestonly_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst.__class__, View)
+ self.assertEqual(ctx, context)
+ return resp
+ class View(object):
+ def __init__(self, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ result = deriver(View)
+ self.failIf(result is View)
+ self.assertEqual(result.__module__, View.__module__)
+ self.assertEqual(result.__doc__, View.__doc__)
+ self.assertEqual(result.__name__, View.__name__)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
+
+ def test_as_oldstyle_cls_context_request_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst.__class__, View)
+ self.assertEqual(ctx, context)
+ return resp
+ class View:
+ def __init__(self, context, request):
+ pass
+ def index(self):
+ return {'a':'1'}
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ result = deriver(View)
+ self.failIf(result is View)
+ self.assertEqual(result.__module__, View.__module__)
+ self.assertEqual(result.__doc__, View.__doc__)
+ self.assertEqual(result.__name__, View.__name__)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
+
+ def test_as_oldstyle_cls_requestonly_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst.__class__, View)
+ self.assertEqual(ctx, context)
+ return resp
+ class View:
def __init__(self, request):
pass
def index(self):
return {'a':'1'}
- result = self._callFUT(view, attr='index', renderer=renderer)
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ result = deriver(View)
+ self.failIf(result is View)
+ self.assertEqual(result.__module__, View.__module__)
+ self.assertEqual(result.__doc__, View.__doc__)
+ self.assertEqual(result.__name__, View.__name__)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
+
+ def test_as_instance_context_and_request_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst, view)
+ self.assertEqual(ctx, context)
+ return resp
+ class View:
+ def index(self, context, request):
+ return {'a':'1'}
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ view = View()
+ result = deriver(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.__module__, view.__module__)
+ self.assertEqual(result.__doc__, view.__doc__)
+ request = self._makeRequest()
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
+
+ def test_as_instance_requestonly_attr_and_renderer(self):
+ class renderer(object):
+ def render_view(inself, req, resp, view_inst, ctx):
+ self.assertEqual(req, request)
+ self.assertEqual(resp, {'a':'1'})
+ self.assertEqual(view_inst, view)
+ self.assertEqual(ctx, context)
+ return resp
+ class View:
+ def index(self, request):
+ return {'a':'1'}
+ deriver = self._makeOne(renderer=renderer(), attr='index')
+ view = View()
+ result = deriver(view)
+ self.failIf(result is view)
+ self.assertEqual(result.__module__, view.__module__)
+ self.assertEqual(result.__doc__, view.__doc__)
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ context = testing.DummyResource()
+ self.assertEqual(result(context, request), {'a':'1'})
- def test__map_view_as_oldstyle_class_context_and_request(self):
- class view:
+class TestDefaultViewMapper(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+ self.registry = self.config.registry
+
+ def tearDown(self):
+ del self.registry
+ testing.tearDown()
+
+ def _makeOne(self, **kw):
+ from pyramid.config import DefaultViewMapper
+ kw['registry'] = self.registry
+ return DefaultViewMapper(**kw)
+
+ def _makeRequest(self):
+ request = DummyRequest()
+ request.registry = self.registry
+ return request
+
+ def test_view_as_function_context_and_request(self):
+ def view(context, request):
+ return 'OK'
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.failUnless(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test__view_as_function_with_attr(self):
+ def view(context, request):
+ """ """
+ mapper = self._makeOne(attr='__name__')
+ result = mapper(view)
+ self.failIf(result is view)
+ request = self._makeRequest()
+ self.assertRaises(TypeError, result, None, request)
+
+ def test_view_as_function_requestonly(self):
+ def view(request):
+ return 'OK'
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.failIf(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_function_requestonly_with_attr(self):
+ def view(request):
+ """ """
+ mapper = self._makeOne(attr='__name__')
+ result = mapper(view)
+ self.failIf(result is view)
+ request = self._makeRequest()
+ self.assertRaises(TypeError, result, None, request)
+
+ 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)
+ mapper = self._makeOne()
+ result = mapper(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')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_oldstyle_class_context_and_request_with_attr(self):
- class view:
+ 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')
+ mapper = self._makeOne(attr='index')
+ result = mapper(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')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_oldstyle_cls_context_request_attr_and_renderer(self):
- renderer = self._registerRenderer()
- class view:
- def __init__(self, context, request):
+ def test_view_as_newstyle_class_requestonly(self):
+ class view(object):
+ def __init__(self, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.failIf(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_newstyle_class_requestonly_with_attr(self):
+ class view(object):
+ def __init__(self, request):
pass
def index(self):
- return {'a':'1'}
- result = self._callFUT(view, attr='index', renderer=renderer)
+ return 'OK'
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_oldstyle_class_requestonly(self):
+ def test_view_as_oldstyle_class_context_and_request(self):
class view:
- def __init__(self, request):
+ def __init__(self, context, request):
pass
def __call__(self):
return 'OK'
- result = self._callFUT(view)
+ mapper = self._makeOne()
+ result = mapper(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')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_oldstyle_class_requestonly_with_attr(self):
+ def test_view_as_oldstyle_class_context_and_request_with_attr(self):
class view:
- def __init__(self, request):
+ def __init__(self, context, request):
pass
def index(self):
return 'OK'
- result = self._callFUT(view, attr='index')
+ mapper = self._makeOne(attr='index')
+ result = mapper(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')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_oldstyle_class_requestonly(self):
+ class view:
+ def __init__(self, request):
+ pass
+ def __call__(self):
+ return 'OK'
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.failIf(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_oldstyle_class_requestonly_attr_and_renderer(self):
- renderer = self._registerRenderer()
+ def test_view_as_oldstyle_class_requestonly_with_attr(self):
class view:
def __init__(self, request):
pass
def index(self):
- return {'a':'1'}
- result = self._callFUT(view, attr='index', renderer=renderer)
+ return 'OK'
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.assertEqual(view.__name__, result.__name__)
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_instance_context_and_request(self):
+ def test_view_as_instance_context_and_request(self):
class View:
def __call__(self, context, request):
return 'OK'
view = View()
- result = self._callFUT(view)
+ mapper = self._makeOne()
+ result = mapper(view)
self.failUnless(result is view)
- self.assertEqual(result(None, None), 'OK')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_instance_context_and_request_and_attr(self):
+ 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__map_view_as_instance_context_and_request_attr_and_renderer(self):
- renderer = self._registerRenderer()
- class View:
- def index(self, context, request):
- return {'a':'1'}
- view = View()
- result = self._callFUT(view, attr='index', renderer=renderer)
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
self.failIf(result is view)
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_instance_requestonly(self):
+ def test_view_as_instance_requestonly(self):
class View:
def __call__(self, request):
return 'OK'
view = View()
- result = self._callFUT(view)
+ mapper = self._makeOne()
+ result = mapper(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')
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
- def test__map_view_as_instance_requestonly_with_attr(self):
+ 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')
+ mapper = self._makeOne(attr='index')
+ result = mapper(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_and_renderer(self):
- renderer = self._registerRenderer()
- class View:
- def index(self, request):
- return {'a':'1'}
- view = View()
- result = self._callFUT(view, attr='index', renderer=renderer)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- self.failUnless('instance' in result.__name__)
- request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test__map_view_rendereronly(self):
- renderer = self._registerRenderer()
- def view(context, request):
- return {'a':'1'}
- result = self._callFUT(view, renderer=renderer)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
- request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
-
- def test__map_view_with_registry(self):
- renderer = self._registerRenderer()
- def view(context, request):
- return {'a':'1'}
- result = self._callFUT(view, renderer=renderer)
- self.failIf(result is view)
- self.assertEqual(view.__module__, result.__module__)
- self.assertEqual(view.__doc__, result.__doc__)
request = self._makeRequest()
- self.assertEqual(result(None, request).body, 'Hello!')
+ self.assertEqual(result(None, request), 'OK')
class Test_preserve_view_attrs(unittest.TestCase):
def _callFUT(self, view, wrapped_view):
@@ -4400,24 +4480,23 @@ class TestMultiView(unittest.TestCase):
response = mv(context, request)
self.assertEqual(response, expected_response)
-
-class TestRequestOnly(unittest.TestCase):
- def _callFUT(self, arg):
+class Test_requestonly(unittest.TestCase):
+ def _callFUT(self, view, attr=None):
from pyramid.config import requestonly
- return requestonly(arg)
+ return requestonly(view, attr)
- def test_newstyle_class_no_init(self):
+ def test_requestonly_newstyle_class_no_init(self):
class foo(object):
""" """
self.assertFalse(self._callFUT(foo))
- def test_newstyle_class_init_toomanyargs(self):
+ def test_requestonly_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):
+ def test_requestonly_newstyle_class_init_onearg_named_request(self):
class foo(object):
def __init__(self, request):
""" """
@@ -4493,6 +4572,22 @@ class TestRequestOnly(unittest.TestCase):
""" """
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):
""" """
diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py
index 7fc066319..69d74ee6e 100644
--- a/pyramid/tests/test_view.py
+++ b/pyramid/tests/test_view.py
@@ -229,11 +229,12 @@ class TestViewConfigDecorator(unittest.TestCase):
def test_create_nondefaults(self):
decorator = self._makeOne(name=None, request_type=None, for_=None,
- permission='foo')
+ permission='foo', view_mapper='mapper')
self.assertEqual(decorator.name, None)
self.assertEqual(decorator.request_type, None)
self.assertEqual(decorator.context, None)
self.assertEqual(decorator.permission, 'foo')
+ self.assertEqual(decorator.view_mapper, 'mapper')
def test_call_function(self):
decorator = self._makeOne()
diff --git a/pyramid/view.py b/pyramid/view.py
index 776185d8b..8f201f6d1 100644
--- a/pyramid/view.py
+++ b/pyramid/view.py
@@ -17,7 +17,6 @@ from zope.interface import providedBy
from pyramid.interfaces import IRoutesMapper
from pyramid.interfaces import IView
from pyramid.interfaces import IViewClassifier
-from pyramid.interfaces import IRendererFactory
from pyramid.httpexceptions import HTTPFound
from pyramid.renderers import RendererHelper
@@ -384,7 +383,7 @@ class view_config(object):
route_name=None, request_method=None, request_param=None,
containment=None, attr=None, renderer=None, wrapper=None,
xhr=False, accept=None, header=None, path_info=None,
- custom_predicates=(), context=None):
+ custom_predicates=(), context=None, view_mapper=None):
self.name = name
self.request_type = request_type
self.context = context or for_
@@ -401,6 +400,7 @@ class view_config(object):
self.header = header
self.path_info = path_info
self.custom_predicates = custom_predicates
+ self.view_mapper = view_mapper
def __call__(self, wrapped):
settings = self.__dict__.copy()