summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Anderson <sontek@gmail.com>2014-12-27 00:18:23 -0800
committerJohn Anderson <sontek@gmail.com>2014-12-27 00:18:23 -0800
commit1236dec0dcfd916bca4e233587f86baa8d2418a8 (patch)
tree1445c35f15b286db3b9c4cb217260a069dc617fe
parente21662924a296f391fdbbf725fb79e409bca59f4 (diff)
downloadpyramid-1236dec0dcfd916bca4e233587f86baa8d2418a8.tar.gz
pyramid-1236dec0dcfd916bca4e233587f86baa8d2418a8.tar.bz2
pyramid-1236dec0dcfd916bca4e233587f86baa8d2418a8.zip
Add the `set_response_factory` API
-rw-r--r--docs/narr/hooks.rst62
-rw-r--r--pyramid/config/__init__.py16
-rw-r--r--pyramid/config/factories.py27
-rw-r--r--pyramid/tests/test_config/test_factories.py15
-rw-r--r--pyramid/tests/test_config/test_init.py12
5 files changed, 130 insertions, 2 deletions
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 4da36e730..f557527bb 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -354,6 +354,68 @@ We attach and cache an object named ``extra`` to the ``request`` object.
.. _beforerender_event:
+.. index::
+ single: response factory
+
+.. _changing_the_response_factory:
+
+Changing the Response Factory
+----------------------------
+
+Whenever :app:`Pyramid` returns a response from a view it creates a
+:term:`response` object. By default, an instance of the
+:class:`pyramid.response.Response` class is created to represent the response
+object.
+
+The class (aka "factory") that :app:`Pyramid` uses to create a response object
+instance can be changed by passing a ``response_factory`` argument to the
+constructor of the :term:`configurator`. This argument can be either a
+callable or a :term:`dotted Python name` representing a callable.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+
+ class MyResponse(Response):
+ pass
+
+ config = Configurator(response_factory=MyResponse)
+
+If you're doing imperative configuration, and you'd rather do it after you've
+already constructed a :term:`configurator` it can also be registered via the
+:meth:`pyramid.config.Configurator.set_response_factory` method:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import Configurator
+ from pyramid.response import Response
+
+ class MyResponse(Response):
+ pass
+
+ config = Configurator()
+ config.set_response_factory(MyRequest)
+
+If you are already using a custom ```request_factory`` you can also set the
+``ResponseClass`` on your :class:`pyramid.request.Request`:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import Configurator
+ from pyramid.response import Response
+ from pyramid.request import Request
+
+ class MyResponse(Response):
+ pass
+
+ class MyRequest(Request):
+ ResponseClass = MyResponse
+
+ config = Configurator()
+
Using The Before Render Event
-----------------------------
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index cfa35ec6c..2ab654b9a 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -179,6 +179,11 @@ class Configurator(
See :ref:`changing_the_request_factory`. By default it is ``None``,
which means use the default request factory.
+ If ``response_factory`` is passed, it should be a :term:`response
+ factory` implementation or a :term:`dotted Python name` to the same.
+ See :ref:`changing_the_response_factory`. By default it is ``None``,
+ which means use the default response factory.
+
If ``default_permission`` is passed, it should be a
:term:`permission` string to be used as the default permission for
all view configuration registrations performed against this
@@ -190,7 +195,7 @@ class Configurator(
configurations which do not explicitly declare a permission will
always be executable by entirely anonymous users (any
authorization policy in effect is ignored).
-
+
.. seealso::
See also :ref:`setting_a_default_permission`.
@@ -254,6 +259,7 @@ class Configurator(
.. versionadded:: 1.6
The ``root_package`` argument.
+ The ``response_factory`` argument.
"""
manager = manager # for testing injection
venusian = venusian # for testing injection
@@ -276,6 +282,7 @@ class Configurator(
debug_logger=None,
locale_negotiator=None,
request_factory=None,
+ response_factory=None,
default_permission=None,
session_factory=None,
default_view_mapper=None,
@@ -310,6 +317,7 @@ class Configurator(
debug_logger=debug_logger,
locale_negotiator=locale_negotiator,
request_factory=request_factory,
+ response_factory=response_factory,
default_permission=default_permission,
session_factory=session_factory,
default_view_mapper=default_view_mapper,
@@ -325,6 +333,7 @@ class Configurator(
debug_logger=None,
locale_negotiator=None,
request_factory=None,
+ response_factory=None,
default_permission=None,
session_factory=None,
default_view_mapper=None,
@@ -412,6 +421,9 @@ class Configurator(
if request_factory:
self.set_request_factory(request_factory)
+ if response_factory:
+ self.set_response_factory(response_factory)
+
if default_permission:
self.set_default_permission(default_permission)
@@ -469,7 +481,7 @@ class Configurator(
_registry.registerSelfAdapter = registerSelfAdapter
# API
-
+
def _get_introspector(self):
introspector = getattr(self.registry, 'introspector', _marker)
if introspector is _marker:
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index 5ce1081c6..d7a48ba93 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -4,6 +4,7 @@ from zope.interface import implementer
from pyramid.interfaces import (
IDefaultRootFactory,
IRequestFactory,
+ IResponseFactory,
IRequestExtensions,
IRootFactory,
ISessionFactory,
@@ -97,6 +98,32 @@ class FactoriesConfiguratorMixin(object):
self.action(IRequestFactory, register, introspectables=(intr,))
@action_method
+ def set_response_factory(self, factory):
+ """ The object passed as ``factory`` should be an object (or a
+ :term:`dotted Python name` which refers to an object) which
+ will be used by the :app:`Pyramid` as the default response
+ objects. This factory object must have the same
+ methods and attributes as the
+ :class:`pyramid.request.Response` class.
+
+ .. note::
+
+ Using the ``response_factory`` argument to the
+ :class:`pyramid.config.Configurator` constructor
+ can be used to achieve the same purpose.
+ """
+ factory = self.maybe_dotted(factory)
+
+ def register():
+ self.registry.registerUtility(factory, IResponseFactory)
+
+ intr = self.introspectable('response factory', None,
+ self.object_description(factory),
+ 'response factory')
+ intr['factory'] = factory
+ self.action(IResponseFactory, register, introspectables=(intr,))
+
+ @action_method
def add_request_method(self,
callable=None,
name=None,
diff --git a/pyramid/tests/test_config/test_factories.py b/pyramid/tests/test_config/test_factories.py
index 6e679397f..c6785d4a5 100644
--- a/pyramid/tests/test_config/test_factories.py
+++ b/pyramid/tests/test_config/test_factories.py
@@ -23,6 +23,21 @@ class TestFactoriesMixin(unittest.TestCase):
self.assertEqual(config.registry.getUtility(IRequestFactory),
dummyfactory)
+ def test_set_response_factory(self):
+ from pyramid.interfaces import IResponseFactory
+ config = self._makeOne(autocommit=True)
+ factory = object()
+ config.set_response_factory(factory)
+ self.assertEqual(config.registry.getUtility(IResponseFactory), factory)
+
+ def test_set_response_factory_dottedname(self):
+ from pyramid.interfaces import IResponseFactory
+ config = self._makeOne(autocommit=True)
+ config.set_response_factory(
+ 'pyramid.tests.test_config.dummyfactory')
+ self.assertEqual(config.registry.getUtility(IResponseFactory),
+ dummyfactory)
+
def test_set_root_factory(self):
from pyramid.interfaces import IRootFactory
config = self._makeOne()
diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py
index c9eaf7c27..8fa6be011 100644
--- a/pyramid/tests/test_config/test_init.py
+++ b/pyramid/tests/test_config/test_init.py
@@ -546,6 +546,18 @@ class ConfiguratorTests(unittest.TestCase):
utility = reg.getUtility(IRequestFactory)
self.assertEqual(utility, factory)
+ def test_setup_registry_response_factory(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IResponseFactory
+ reg = Registry()
+ config = self._makeOne(reg)
+ factory = object()
+ config.setup_registry(response_factory=factory)
+ self.assertEqual(reg.queryUtility(IResponseFactory), None)
+ config.commit()
+ utility = reg.getUtility(IResponseFactory)
+ self.assertEqual(utility, factory)
+
def test_setup_registry_request_factory_custom_response_class(self):
from pyramid.registry import Registry
from pyramid.interfaces import IRequestFactory