summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-06-14 02:36:07 -0400
committerChris McDonough <chrism@plope.com>2011-06-14 02:36:07 -0400
commit1a6fc7062f803b9f15b7677db9a9257a4f00bfcb (patch)
tree47048dadf66f6aad3c6ef9ef9752c11d9338e827
parent3f4f67e76c2e1338377babd983e4071f52235132 (diff)
downloadpyramid-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.txt6
-rw-r--r--docs/api/config.rst2
-rw-r--r--docs/narr/hooks.rst13
-rw-r--r--pyramid/config.py42
-rw-r--r--pyramid/registry.py3
-rw-r--r--pyramid/router.py2
-rw-r--r--pyramid/tests/test_config.py28
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