diff options
| author | Chris McDonough <chrism@plope.com> | 2011-06-14 02:36:07 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-06-14 02:36:07 -0400 |
| commit | 1a6fc7062f803b9f15b7677db9a9257a4f00bfcb (patch) | |
| tree | 47048dadf66f6aad3c6ef9ef9752c11d9338e827 | |
| parent | 3f4f67e76c2e1338377babd983e4071f52235132 (diff) | |
| download | pyramid-1a6fc7062f803b9f15b7677db9a9257a4f00bfcb.tar.gz pyramid-1a6fc7062f803b9f15b7677db9a9257a4f00bfcb.tar.bz2 pyramid-1a6fc7062f803b9f15b7677db9a9257a4f00bfcb.zip | |
- Added new add_response_adapter method to Configurator.
- Fix Configurator docstring wrt exception responses.
- Speed up registry.queryAdapterOrSelf
| -rw-r--r-- | CHANGES.txt | 6 | ||||
| -rw-r--r-- | docs/api/config.rst | 2 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 13 | ||||
| -rw-r--r-- | pyramid/config.py | 42 | ||||
| -rw-r--r-- | pyramid/registry.py | 3 | ||||
| -rw-r--r-- | pyramid/router.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_config.py | 28 |
7 files changed, 70 insertions, 26 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 5e8df1a0b..c7ca3794d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -130,8 +130,10 @@ Features - It is now possible to return an arbitrary object from a Pyramid view callable even if a renderer is not used, as long as a suitable adapter to ``pyramid.interfaces.IResponse`` is registered for the type of the returned - object. See the section in the Hooks chapter of the documentation entitled - "Changing How Pyramid Treats View Responses". + object by using the new + ``pyramid.config.Configurator.add_response_adapter`` API. See the section + in the Hooks chapter of the documentation entitled "Changing How Pyramid + Treats View Responses". - The Pyramid router will now, by default, call the ``__call__`` method of WebOb response objects when returning a WSGI response. This means that, diff --git a/docs/api/config.rst b/docs/api/config.rst index 2b9d7bcef..274ee0292 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -40,6 +40,8 @@ .. automethod:: add_renderer(name, factory) + .. automethod:: add_response_adapter + .. automethod:: add_route .. automethod:: add_static_view(name, path, cache_max_age=3600, permission='__no_permission_required__') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 0db8ce5e0..8e5b93ed4 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -532,7 +532,7 @@ Changing How Pyramid Treats View Responses It is possible to control how Pyramid treats the result of calling a view callable on a per-type basis by using a hook involving -:class:`pyramid.interfaces.IResponse`. +:method:`pyramid.config.Configurator.add_response_adapter`. .. note:: This feature is new as of Pyramid 1.1. @@ -559,7 +559,6 @@ Response: .. code-block:: python :linenos: - from pyramid.interfaces import IResponse from pyramid.response import Response def string_response_adapter(s): @@ -568,8 +567,7 @@ Response: # config is an instance of pyramid.config.Configurator - config.registry.registerAdapter(string_response_adapter, (str,), - IResponse) + config.add_response_adapter(string_response_adapter, str) Likewise, if you want to be able to return a simplified kind of response object from view callables, you can use the IResponse hook to register an @@ -578,7 +576,6 @@ adapter to the more complex IResponse interface: .. code-block:: python :linenos: - from pyramid.interfaces import IResponse from pyramid.response import Response class SimpleResponse(object): @@ -591,14 +588,12 @@ adapter to the more complex IResponse interface: # config is an instance of pyramid.config.Configurator - config.registry.registerAdapter(simple_response_adapter, - (SimpleResponse,), - IResponse) + config.add_response_adapter(simple_response_adapter, SimpleResponse) If you want to implement your own Response object instead of using the :class:`pyramid.response.Response` object in any capacity at all, you'll have to make sure the object implements every attribute and method outlined in -:class:`pyramid.interfaces.IResponse` *and* you'll have to ensure that it's +:class:`pyramid.interfaces.IResponse` and you'll have to ensure that it's marked up with ``zope.interface.implements(IResponse)``: from pyramid.interfaces import IResponse diff --git a/pyramid/config.py b/pyramid/config.py index dbeb0788c..70b5cd639 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -19,7 +19,6 @@ from zope.interface import implementedBy from zope.interface.interfaces import IInterface from zope.interface import implements from zope.interface import classProvides -from zope.interface import providedBy from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy @@ -260,15 +259,11 @@ class Configurator(object): If ``exceptionresponse_view`` is passed, it must be a :term:`view callable` or ``None``. If it is a view callable, it will be used as an - exception view callable when an :term:`exception response` is raised (any - object that implements the :class:`pyramid.interaces.IExceptionResponse` - interface, such as a :class:`pyramid.response.Response` object or any - ``HTTP`` exception documented in :mod:`pyramid.httpexceptions` as well as - exception responses raised via :func:`pyramid.exceptions.abort`, - :func:`pyramid.exceptions.redirect`). If ``exceptionresponse_view`` is - ``None``, no exception response view will be registered, and all raised - exception responses will be bubbled up to Pyramid's caller. By - default, the ``pyramid.exceptions.default_exceptionresponse_view`` + exception view callable when an :term:`exception response` is raised. If + ``exceptionresponse_view`` is ``None``, no exception response view will + be registered, and all raised exception responses will be bubbled up to + Pyramid's caller. By + default, the ``pyramid.httpexceptions.default_exceptionresponse_view`` function is used as the ``exceptionresponse_view``. This argument is new in Pyramid 1.1. """ @@ -433,8 +428,7 @@ class Configurator(object): if not hasattr(_registry, 'queryAdapterOrSelf'): def queryAdapterOrSelf(object, interface, default=None): - provides = providedBy(object) - if not interface in provides: + if not interface.providedBy(object): return _registry.queryAdapter(object, interface, default=default) return object @@ -893,6 +887,30 @@ class Configurator(object): self.action(None, register) return subscriber + @action_method + def add_response_adapter(self, adapter, type_or_iface): + """ When an object of type (or interface) ``type_or_iface`` is + returned from a view callable, Pyramid will use the adapter + ``adapter`` to convert it into an object which implements the + :class:`pyramid.interfaces.IResponse` interface. If ``adapter`` is + None, an object returned of type (or interface) ``type_or_iface`` + will itself be used as a response object. + + ``adapter`` and ``type_or_interface`` may be Python objects or + strings representing dotted names to importable Python global + objects. + + See :ref:`using_iresponse` for more information.""" + adapter = self.maybe_dotted(adapter) + type_or_iface = self.maybe_dotted(type_or_iface) + def register(): + reg = self.registry + if adapter is None: + reg.registerSelfAdapter((type_or_iface,), IResponse) + else: + reg.registerAdapter(adapter, (type_or_iface,), IResponse) + self.action((IResponse, type_or_iface), register) + def add_settings(self, settings=None, **kw): """Augment the ``settings`` argument passed in to the Configurator constructor with one or more 'setting' key/value pairs. A setting is diff --git a/pyramid/registry.py b/pyramid/registry.py index 4c6262ce1..5db0a11e2 100644 --- a/pyramid/registry.py +++ b/pyramid/registry.py @@ -41,8 +41,7 @@ class Registry(Components, dict): # queryAdapter analogue which returns the object if it implements # the interface, otherwise it will return an adaptation to the # interface - provides = providedBy(object) - if not interface in provides: + if not interface.providedBy(object): return self.queryAdapter(object, interface, default=default) return object diff --git a/pyramid/router.py b/pyramid/router.py index 48640b39d..8e33332df 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -185,7 +185,7 @@ class Router(object): if response is None: raise ValueError( 'Could not convert view return value "%s" into a ' - 'response' % (result,)) + 'response object' % (result,)) has_listeners and registry.notify(NewResponse(request,response)) diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py index 49bfab396..cc4a037c2 100644 --- a/pyramid/tests/test_config.py +++ b/pyramid/tests/test_config.py @@ -2628,6 +2628,34 @@ class ConfiguratorTests(unittest.TestCase): self.assertEqual(config.registry.getUtility(IRendererFactory, 'name'), pyramid.tests) + def test_add_response_adapter(self): + from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) + class Adapter(object): + def __init__(self, other): + self.other = other + config.add_response_adapter(Adapter, str) + result = config.registry.queryAdapter('foo', IResponse) + self.assertTrue(result.other, 'foo') + + def test_add_response_adapter_self(self): + from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) + class Adapter(object): + pass + config.add_response_adapter(None, Adapter) + adapter = Adapter() + result = config.registry.queryAdapter(adapter, IResponse) + self.assertTrue(result is adapter) + + def test_add_response_adapter_dottednames(self): + from pyramid.interfaces import IResponse + config = self._makeOne(autocommit=True) + config.add_response_adapter('pyramid.response.Response', + 'types.StringType') + result = config.registry.queryAdapter('foo', IResponse) + self.assertTrue(result.body, 'foo') + def test_scan_integration(self): import os from zope.interface import alsoProvides |
