Skip to content

Commit

Permalink
make use_tweens=False the default
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdonc committed Sep 17, 2012
1 parent dace598 commit db2a037
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
5 changes: 4 additions & 1 deletion docs/api/request.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
request, the value of this attribute will be ``None``. See
:ref:`matched_route`.

.. method:: invoke_subrequest(request, use_tweens=True)
.. method:: invoke_subrequest(request, use_tweens=False)

.. warning::

Expand Down Expand Up @@ -198,6 +198,9 @@
- causes a :class:`~pyramid.event.ContextFound` event to be sent
when a context resource is found.

- Ensures that the user implied by the request passed has the necessary
authorization to invoke view callable before calling it.

- causes a :class:`~pyramid.event.NewResponse` event to be sent when
the Pyramid application returns a response.

Expand Down
63 changes: 40 additions & 23 deletions docs/narr/subrequest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ request along to :meth:`pyramid.request.Request.invoke_subrequest`. The
the ``view_two`` view callable.

Note that it doesn't matter if the view callable invoked via a subrequest
actually returns a literal Response object. Any view callable that uses a
actually returns a *literal* Response object. Any view callable that uses a
renderer or which returns an object that can be interpreted by a response
adapter will work too:
adapter when found and invoked via
:meth:`pyramid.request.Request.invoke_subrequest` will return a Response
object:

.. code-block:: python
Expand Down Expand Up @@ -97,8 +99,9 @@ callable directly. Subrequests are slower and are less convenient if you
actually do want just the literal information returned by a function that
happens to be a view callable.

Note that if a view callable invoked by a subrequest raises an exception, the
exception will usually be converted to a response if you have a
Note that, by default, if a view callable invoked by a subrequest raises an
exception, the exception will be raised to the caller of
:meth:`~pyramid.request.Request.invoke_subrequest` even if you have a
:term:`exception view` configured:

.. code-block:: python
Expand Down Expand Up @@ -131,14 +134,16 @@ exception will usually be converted to a response if you have a
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Because the exception view handling tween is generally in the tween list, if
we run the above code, the ``excview`` :term:`exception view` will generate a
"500" error response, which will be returned to us within ``view_one``: a
Python exception will not be raised.
When we run the above code and visit ``/view_one`` in a browser, the
``excview`` :term:`exception view` will *not* be executed. Instead, the call
to :meth:`~pyramid.request.Request.invoke_subrequest` will cause a
:exc:`ValueError` exception to be raised and a response will never be
generated. We can change this behavior; how to do so is described below in
our discussion of the ``use_tweens`` argument.

The :meth:`pyramid.request.Request.invoke_subrequest` API accepts two
arguments: a positional argument ``request`` that must be provided, and and
``use_tweens`` keyword argument that is optional; it defaults to ``True``.
``use_tweens`` keyword argument that is optional; it defaults to ``False``.

The ``request`` object passed to the API must be an object that implements
the Pyramid request interface (such as a :class:`pyramid.request.Request`
Expand All @@ -148,13 +153,16 @@ instance). If ``use_tweens`` is ``True``, the request will be sent to the
handler, and no tweens will be invoked.

In the example above, the call to
:meth:`~pyramid.request.Request.invoke_subrequest` will generally always
return a Response object, even when the view it invokes raises an exception,
because it uses the default ``use_tweens=True`` and a :term:`exception view`
is configured.

We can cause the subrequest to not be run through the tween stack by passing
``use_tweens=False`` to the call to
:meth:`~pyramid.request.Request.invoke_subrequest` will always raise an
exception. This is because it's using the default value for ``use_tweens``,
which is ``False``. You can pass ``use_tweens=True`` instead to ensure that
it will convert an exception to a Response if an :term:`exception view` is
configured instead of raising the exception. This because exception views
are called by the exception view :term:`tween` as described in
:ref:`exception_views` when any view raises an exception.

We can cause the subrequest to be run through the tween stack by passing
``use_tweens=True`` to the call to
:meth:`~pyramid.request.Request.invoke_subrequest`, like this:

.. code-block:: python
Expand All @@ -165,7 +173,7 @@ We can cause the subrequest to not be run through the tween stack by passing
def view_one(request):
subreq = Request.blank('/view_two')
response = request.invoke_subrequest(subreq, use_tweens=False)
response = request.invoke_subrequest(subreq, use_tweens=True)
return response
def view_two(request):
Expand All @@ -187,11 +195,11 @@ We can cause the subrequest to not be run through the tween stack by passing
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
In the above case, the call to ``request.invoke_subrequest(subreq)`` will
actually raise a :exc:`ValueError` exception instead of retrieving a "500"
response from the attempted invocation of ``view_two``, because the tween
which invokes an exception view to generate a response is never run, and
therefore ``excview`` is never executed.
In the above case, the call to ``request.invoke_subrequest(subreq)`` will not
raise an exception. Instead, it will retrieve a "500" response from the
attempted invocation of ``view_two``, because the tween which invokes an
exception view to generate a response is run, and therefore ``excview`` is
executed.

This is one of the major differences between specifying the
``use_tweens=True`` and ``use_tweens=False`` arguments to
Expand All @@ -201,7 +209,8 @@ subrequest if you've got ``pyramid_tm`` in the tween list, injecting debug
HTML if you've got ``pyramid_debugtoolbar`` in the tween list, and other
tween-related side effects as defined by your particular tween list.

The :meth:`~pyramid.request.Request.invoke_subrequest` function also:
The :meth:`~pyramid.request.Request.invoke_subrequest` function also
unconditionally:

- manages the threadlocal stack so that
:func:`~pyramid.threadlocal.get_current_request` and
Expand All @@ -222,6 +231,9 @@ The :meth:`~pyramid.request.Request.invoke_subrequest` function also:
- causes a :class:`~pyramid.event.ContextFound` event to be sent when a
context resource is found.

- Ensures that the user implied by the request passed has the necessary
authorization to invoke view callable before calling it.

- causes a :class:`~pyramid.event.NewResponse` event to be sent when the
Pyramid application returns a response.

Expand All @@ -231,6 +243,11 @@ The :meth:`~pyramid.request.Request.invoke_subrequest` function also:
- Calls any :term:`finished callback` functions defined within the subrequest's
lifetime.

The invocation of a subrequest has more or less exactly the same effect as
the invocation of a request received by the Pyramid router from a web client
when ``use_tweens=True``. When ``use_tweens=False``, the tweens are skipped
but all the other steps take place.

It's a poor idea to use the original ``request`` object as an argument to
:meth:`~pyramid.request.Request.invoke_subrequest`. You should construct a
new request instead as demonstrated in the above example, using
Expand Down
10 changes: 10 additions & 0 deletions docs/narr/views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,16 @@ exception views which have a name will be ignored.
Exception views can be configured with any view registration mechanism:
``@view_config`` decorator or imperative ``add_view`` styles.

.. note::

Pyramid's :term:`exception view` handling logic is implemented as a tween
factory function: :func:`pyramid.tweens.excview_tween_factory`. If
Pyramid exception view handling is desired, and tween factories are
specified via the ``pyramid.tweens`` configuration setting, the
:func:`pyramid.tweens.excview_tween_factory` function must be added to the
``pyramid.tweens`` configuration setting list explicitly. If it is not
present, Pyramid will not perform exception view handling.

.. index::
single: view http redirect
single: http redirect (from a view)
Expand Down
2 changes: 1 addition & 1 deletion pyramid/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def handle_request(self, request):

return response

def invoke_subrequest(self, request, use_tweens=True):
def invoke_subrequest(self, request, use_tweens=False):
"""
Obtain a response object from the Pyramid application based on
information in the ``request`` object provided. The ``request``
Expand Down

0 comments on commit db2a037

Please sign in to comment.