From 37d2c224b804dfebe9ee217c7a536364eacdee15 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:25:17 -0400 Subject: docs and test --- docs/narr/subrequest.rst | 143 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 docs/narr/subrequest.rst (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst new file mode 100644 index 000000000..6ed679579 --- /dev/null +++ b/docs/narr/subrequest.rst @@ -0,0 +1,143 @@ +.. index:: + single: subrequest + +.. _subrequest_chapter: + +Invoking a Subrequest +===================== + +.. warning:: + + This feature was added in Pyramid 1.4a1. + +:app:`Pyramid` allows you to invoke a subrequest at any point during the +processing of a request. Invoking a subrequest allows you to obtain a +:term:`response` object from a view callable within your :app:`Pyramid` +application while you're executing a different view callable within the same +application. + +Here's an example application which uses a subrequest: + +.. code-block:: python + + from wsgiref.simple_server import make_server + from pyramid.config import Configurator + from pyramid.request import Request + + def view_one(request): + subreq = Request.blank('/view_two') + response = request.subrequest(subreq) + return response + + def view_two(request): + request.response.body = 'This came from view_two' + return request.response + + if __name__ == '__main__': + config = Configurator() + config.add_route('one', '/view_one') + config.add_route('two', '/view_two') + config.add_view(view_one, route_name='one') + config.add_view(view_two, route_name='two') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 8080, app) + server.serve_forever() + +When ``/view_one`` is visted in a browser, the text printed in the browser +pane will be ``This came from view_two``. The ``view_one`` view used the +:meth:`pyramid.request.Request.subrequest` API to obtain a response from +another view (``view_two``) within the same application when it executed. It +did so by constructing a new request that had a URL that it knew would match +the ``view_two`` view registration, and passed that new request along to +:meth:`pyramid.request.Request.subrequest`. The ``view_two`` view callable +was invoked, and it returned a response. The ``view_one`` view callable then +simply returned the response it obtained from 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 +renderer or which returns an object that can be interpreted by a response +adapter will work too: + +.. code-block:: python + + from wsgiref.simple_server import make_server + from pyramid.config import Configurator + from pyramid.request import Request + + def view_one(request): + subreq = Request.blank('/view_two') + response = request.subrequest(subreq) + return response + + def view_two(request): + return 'This came from view_two' + + if __name__ == '__main__': + config = Configurator() + config.add_route('one', '/view_one') + config.add_route('two', '/view_two') + config.add_view(view_one, route_name='one') + config.add_view(view_two, route_name='two', renderer='string') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 8080, app) + server.serve_forever() + +Being able to unconditionally obtain a response object by invoking a view +callable indirectly is the main advantage to using +:meth:`pyramid.request.Request.subrequest` instead of simply importing it and +executing it directly. Note that there's not much advantage to invoking a +view using a subrequest if you *can* invoke a view callable directly. It's +much slower to use a subrequest. + +The :meth:`pyramid.request.Request.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 ``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` +instance). If ``use_tweens`` is ``True``, the request will be sent to the +:term:`tween` in the tween stack closest to the request ingress. If +``use_tweens`` is ``False``, the request will be sent to the main router +handler, and no tweens will be invoked. It's usually best to not invoke any +tweens when executing a subrequest, because the original request will invoke +any tween logic as necessary. The :meth:`pyramid.request.Request.subrequest` +function also: + +- manages the threadlocal stack so that + :func:`~pyramid.threadlocal.get_current_request` and + :func:`~pyramid.threadlocal.get_current_registry` work during a request + (they will return the subrequest instead of the original request) + +- Adds a ``registry`` attribute and a ``subrequest`` attribute to the request + object it's handed. + +- sets request extensions (such as those added via + :meth:`~pyramid.config.Configurator.add_request_method` or + :meth:`~pyramid.config.Configurator.set_request_property`) on the subrequest + object passed as ``request`` + +- causes a :class:`~pyramid.event.NewRequest` event to be sent at the + beginning of request processing. + +- causes a :class:`~pyramid.event.ContextFound` event to be sent when a + context resource is found. + +- causes a :class:`~pyramid.event.NewResponse` event to be sent when the + Pyramid application returns a response. + +- Calls any :term:`response callback` functions defined within the subrequest's + lifetime if a response is obtained from the Pyramid application. + +- Calls any :term:`finished callback` functions defined within the subrequest's + lifetime. + +It's a poor idea to use the original ``request`` object as an argument to +:meth:`~pyramid.request.Request.subrequest`. You should construct a new +request instead as demonstrated in the above example, using +:meth:`pyramid.request.Request.blank`. Once you've constructed a request +object, you'll need to massage the it to match the view callable you'd like +to be executed during the subrequest. This can be done by adjusting the +subrequest's URL, its headers, its request method, and other attributes. See +the documentation for :class:`pyramid.request.Request` to understand how to +massage your new request object into something that will match the view you'd +like to call via a subrequest. -- cgit v1.2.3 From 3f3917f9c70ddc83263e440a8bc781bacb33bb6e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:27:00 -0400 Subject: moar --- docs/narr/subrequest.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 6ed679579..5067fa890 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -84,10 +84,10 @@ adapter will work too: Being able to unconditionally obtain a response object by invoking a view callable indirectly is the main advantage to using -:meth:`pyramid.request.Request.subrequest` instead of simply importing it and -executing it directly. Note that there's not much advantage to invoking a -view using a subrequest if you *can* invoke a view callable directly. It's -much slower to use a subrequest. +:meth:`pyramid.request.Request.subrequest` instead of simply importing the +view callable and executing it directly. Note that there's not much +advantage to invoking a view using a subrequest if you *can* invoke a view +callable directly. It's much slower to use a subrequest. The :meth:`pyramid.request.Request.subrequest` API accepts two arguments: a positional argument ``request`` that must be provided, and and ``use_tweens`` @@ -141,3 +141,7 @@ subrequest's URL, its headers, its request method, and other attributes. See the documentation for :class:`pyramid.request.Request` to understand how to massage your new request object into something that will match the view you'd like to call via a subrequest. + +We've demonstrated use of a subrequest from within a view callable, but you +can use the :meth:`~pyramid.request.Request.subrequest` API from within a +tween or an event handler as well. -- cgit v1.2.3 From ab84e1038b9004c978ea49829c2d1b7a2d48d3d4 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:30:28 -0400 Subject: explain --- docs/narr/subrequest.rst | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 5067fa890..045cec279 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -82,6 +82,11 @@ adapter will work too: server = make_server('0.0.0.0', 8080, app) server.serve_forever() +Even though the ``view_two`` view callable returned a string, it was invoked +in such a way that the ``string`` renderer associated with the view +registration that was found turned it into a "real" response object for +consumption by ``view_one``. + Being able to unconditionally obtain a response object by invoking a view callable indirectly is the main advantage to using :meth:`pyramid.request.Request.subrequest` instead of simply importing the -- cgit v1.2.3 From fef69b67c5d07f7b7294fe9b52f70fb9de22d17f Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:31:40 -0400 Subject: explain --- docs/narr/subrequest.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 045cec279..8429fe7fe 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -92,7 +92,9 @@ callable indirectly is the main advantage to using :meth:`pyramid.request.Request.subrequest` instead of simply importing the view callable and executing it directly. Note that there's not much advantage to invoking a view using a subrequest if you *can* invoke a view -callable directly. It's much slower to use a subrequest. +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. The :meth:`pyramid.request.Request.subrequest` API accepts two arguments: a positional argument ``request`` that must be provided, and and ``use_tweens`` -- cgit v1.2.3 From 1e59ef41026d9754ac9dc21522dd68edfcaf18d7 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:37:37 -0400 Subject: garden todo, add docs about exception handling --- docs/narr/subrequest.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 8429fe7fe..39f985520 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -96,6 +96,36 @@ 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 bubble up to the invoking code: + +.. code-block:: python + + from wsgiref.simple_server import make_server + from pyramid.config import Configurator + from pyramid.request import Request + + def view_one(request): + subreq = Request.blank('/view_two') + response = request.subrequest(subreq) + return response + + def view_two(request): + raise ValueError('foo') + + if __name__ == '__main__': + config = Configurator() + config.add_route('one', '/view_one') + config.add_route('two', '/view_two') + config.add_view(view_one, route_name='one') + config.add_view(view_two, route_name='two', renderer='string') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 8080, app) + server.serve_forever() + +In the above application, the call to ``request.subrequest(subreq)`` will +raise a :exc:`ValueError` exception instead of obtaining a "500" response. + The :meth:`pyramid.request.Request.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 ``False``. -- cgit v1.2.3 From b895defdcecbf9d758ad92b1bbf6a49f21620c8a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:39:26 -0400 Subject: wording --- docs/narr/subrequest.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 39f985520..4f132f72f 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -124,7 +124,8 @@ exception will usually bubble up to the invoking code: server.serve_forever() In the above application, the call to ``request.subrequest(subreq)`` will -raise a :exc:`ValueError` exception instead of obtaining a "500" response. +actually raise a :exc:`ValueError` exception instead of retrieving a "500" +response from the attempted invocation of ``view_two``. The :meth:`pyramid.request.Request.subrequest` API accepts two arguments: a positional argument ``request`` that must be provided, and and ``use_tweens`` -- cgit v1.2.3 From 64452edb014423054d1bbc0bb3ed8a3e47b6f611 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 03:54:08 -0400 Subject: rename subrequest to invoke_subrequest --- docs/narr/subrequest.rst | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 4f132f72f..bd50b6053 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -26,7 +26,7 @@ Here's an example application which uses a subrequest: def view_one(request): subreq = Request.blank('/view_two') - response = request.subrequest(subreq) + response = request.invoke_subrequest(subreq) return response def view_two(request): @@ -45,13 +45,14 @@ Here's an example application which uses a subrequest: When ``/view_one`` is visted in a browser, the text printed in the browser pane will be ``This came from view_two``. The ``view_one`` view used the -:meth:`pyramid.request.Request.subrequest` API to obtain a response from -another view (``view_two``) within the same application when it executed. It -did so by constructing a new request that had a URL that it knew would match -the ``view_two`` view registration, and passed that new request along to -:meth:`pyramid.request.Request.subrequest`. The ``view_two`` view callable -was invoked, and it returned a response. The ``view_one`` view callable then -simply returned the response it obtained from the ``view_two`` view callable. +:meth:`pyramid.request.Request.invoke_subrequest` API to obtain a response +from another view (``view_two``) within the same application when it +executed. It did so by constructing a new request that had a URL that it +knew would match the ``view_two`` view registration, and passed that new +request along to :meth:`pyramid.request.Request.invoke_subrequest`. The +``view_two`` view callable was invoked, and it returned a response. The +``view_one`` view callable then simply returned the response it obtained from +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 @@ -66,7 +67,7 @@ adapter will work too: def view_one(request): subreq = Request.blank('/view_two') - response = request.subrequest(subreq) + response = request.invoke_subrequest(subreq) return response def view_two(request): @@ -89,8 +90,8 @@ consumption by ``view_one``. Being able to unconditionally obtain a response object by invoking a view callable indirectly is the main advantage to using -:meth:`pyramid.request.Request.subrequest` instead of simply importing the -view callable and executing it directly. Note that there's not much +:meth:`pyramid.request.Request.invoke_subrequest` instead of simply importing +the view callable and executing it directly. Note that there's not much advantage to invoking a view using a subrequest if you *can* invoke a view callable directly. Subrequests are slower and are less convenient if you actually do want just the literal information returned by a function that @@ -107,7 +108,7 @@ exception will usually bubble up to the invoking code: def view_one(request): subreq = Request.blank('/view_two') - response = request.subrequest(subreq) + response = request.invoke_subrequest(subreq) return response def view_two(request): @@ -123,13 +124,13 @@ exception will usually bubble up to the invoking code: server = make_server('0.0.0.0', 8080, app) server.serve_forever() -In the above application, the call to ``request.subrequest(subreq)`` will -actually raise a :exc:`ValueError` exception instead of retrieving a "500" -response from the attempted invocation of ``view_two``. +In the above application, 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``. -The :meth:`pyramid.request.Request.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 ``False``. +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 ``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` @@ -138,16 +139,16 @@ instance). If ``use_tweens`` is ``True``, the request will be sent to the ``use_tweens`` is ``False``, the request will be sent to the main router handler, and no tweens will be invoked. It's usually best to not invoke any tweens when executing a subrequest, because the original request will invoke -any tween logic as necessary. The :meth:`pyramid.request.Request.subrequest` -function also: +any tween logic as necessary. The +:meth:`pyramid.request.Request.invoke_subrequest` function also: - manages the threadlocal stack so that :func:`~pyramid.threadlocal.get_current_request` and :func:`~pyramid.threadlocal.get_current_registry` work during a request (they will return the subrequest instead of the original request) -- Adds a ``registry`` attribute and a ``subrequest`` attribute to the request - object it's handed. +- Adds a ``registry`` attribute and a ``invoke_subrequest`` attribute (a + callable) to the request object it's handed. - sets request extensions (such as those added via :meth:`~pyramid.config.Configurator.add_request_method` or @@ -170,8 +171,8 @@ function also: lifetime. It's a poor idea to use the original ``request`` object as an argument to -:meth:`~pyramid.request.Request.subrequest`. You should construct a new -request instead as demonstrated in the above example, using +:meth:`~pyramid.request.Request.invoke_subrequest`. You should construct a +new request instead as demonstrated in the above example, using :meth:`pyramid.request.Request.blank`. Once you've constructed a request object, you'll need to massage the it to match the view callable you'd like to be executed during the subrequest. This can be done by adjusting the @@ -181,5 +182,5 @@ massage your new request object into something that will match the view you'd like to call via a subrequest. We've demonstrated use of a subrequest from within a view callable, but you -can use the :meth:`~pyramid.request.Request.subrequest` API from within a -tween or an event handler as well. +can use the :meth:`~pyramid.request.Request.invoke_subrequest` API from +within a tween or an event handler as well. -- cgit v1.2.3 From 7259e7e9f3d8f8eb70bcf782f622f8613f99a51d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 13:04:14 -0400 Subject: make use_tweens=True the default, add some more tests --- docs/narr/subrequest.rst | 83 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 15 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index bd50b6053..1c26da73a 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -91,14 +91,14 @@ consumption by ``view_one``. Being able to unconditionally obtain a response object by invoking a view callable indirectly is the main advantage to using :meth:`pyramid.request.Request.invoke_subrequest` instead of simply importing -the view callable and executing it directly. Note that there's not much +a view callable and executing it directly. Note that there's not much advantage to invoking a view using a subrequest if you *can* invoke a view 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 bubble up to the invoking code: +exception will usually be converted to a response: .. code-block:: python @@ -124,23 +124,69 @@ exception will usually bubble up to the invoking code: server = make_server('0.0.0.0', 8080, app) server.serve_forever() -In the above application, 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 exception view handling tween is generally in the tween list, if +we run the above code, the default :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. 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 ``False``. +``use_tweens`` keyword argument that is optional; it defaults to ``True``. The ``request`` object passed to the API must be an object that implements the Pyramid request interface (such as a :class:`pyramid.request.Request` instance). If ``use_tweens`` is ``True``, the request will be sent to the :term:`tween` in the tween stack closest to the request ingress. If ``use_tweens`` is ``False``, the request will be sent to the main router -handler, and no tweens will be invoked. It's usually best to not invoke any -tweens when executing a subrequest, because the original request will invoke -any tween logic as necessary. The -:meth:`pyramid.request.Request.invoke_subrequest` function also: +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``. + +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`, like this: + +.. code-block:: python + + from wsgiref.simple_server import make_server + from pyramid.config import Configurator + from pyramid.request import Request + + def view_one(request): + subreq = Request.blank('/view_two') + response = request.invoke_subrequest(subreq, use_tweens=False) + return response + + def view_two(request): + raise ValueError('foo') + + if __name__ == '__main__': + config = Configurator() + config.add_route('one', '/view_one') + config.add_route('two', '/view_two') + config.add_view(view_one, route_name='one') + config.add_view(view_two, route_name='two', renderer='string') + app = config.make_wsgi_app() + 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. + +This is one of the major differences between specifying the +``use_tweens=True`` and ``use_tweens=False`` arguments to +:meth:`~pyramid.request.Request.invoke_subrequest`. ``use_tweens=True`` may +also imply invoking transaction commit/abort for the logic executed in the +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: - manages the threadlocal stack so that :func:`~pyramid.threadlocal.get_current_request` and @@ -176,11 +222,18 @@ new request instead as demonstrated in the above example, using :meth:`pyramid.request.Request.blank`. Once you've constructed a request object, you'll need to massage the it to match the view callable you'd like to be executed during the subrequest. This can be done by adjusting the -subrequest's URL, its headers, its request method, and other attributes. See -the documentation for :class:`pyramid.request.Request` to understand how to -massage your new request object into something that will match the view you'd -like to call via a subrequest. +subrequest's URL, its headers, its request method, and other attributes. The +documentation for :class:`pyramid.request.Request` exposes the methods you +should call and attributes you should set on the request you create to +massage it into something that will actually match the view you'd like to +call via a subrequest. We've demonstrated use of a subrequest from within a view callable, but you can use the :meth:`~pyramid.request.Request.invoke_subrequest` API from -within a tween or an event handler as well. +within a tween or an event handler as well. It's usually a poor idea to +invoke :meth:`~pyramid.request.Request.invoke_subrequest` from within a +tween, because tweens already by definition have access to a function that +will cause a subrequest (they are passed a ``handle`` function), but you can +do it. It's fine to invoke +:meth:`~pyramid.request.Request.invoke_subrequest` from within an event +handler, however. -- cgit v1.2.3 From 0966cfb8bd7ac43f8ce3b6dd903b03ae3bab8ac6 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 13:08:42 -0400 Subject: explain how this works with the exception view --- docs/narr/subrequest.rst | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 1c26da73a..43876b45a 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -98,7 +98,8 @@ 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: +exception will usually be converted to a response if you have a +:term:`exception view` configured: .. code-block:: python @@ -114,20 +115,26 @@ exception will usually be converted to a response: def view_two(request): raise ValueError('foo') + def excview(request): + request.response.body = b'An exception was raised' + request.response.status_int = 500 + return request.response + if __name__ == '__main__': config = Configurator() config.add_route('one', '/view_one') config.add_route('two', '/view_two') config.add_view(view_one, route_name='one') config.add_view(view_two, route_name='two', renderer='string') + config.add_view(excview, context=Exception) app = config.make_wsgi_app() 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 default :term:`exception view` will generate a +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. +Python exception will not be raised. The :meth:`pyramid.request.Request.invoke_subrequest` API accepts two arguments: a positional argument ``request`` that must be provided, and and @@ -143,7 +150,8 @@ 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``. +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 @@ -163,12 +171,18 @@ We can cause the subrequest to not be run through the tween stack by passing def view_two(request): raise ValueError('foo') + def excview(request): + request.response.body = b'An exception was raised' + request.response.status_int = 500 + return request.response + if __name__ == '__main__': config = Configurator() config.add_route('one', '/view_one') config.add_route('two', '/view_two') config.add_view(view_one, route_name='one') config.add_view(view_two, route_name='two', renderer='string') + config.add_view(excview, context=Exception) app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever() @@ -176,7 +190,8 @@ We can cause the subrequest to not be run through the tween stack by passing 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. +which invokes an exception view to generate a response is never run, and +therefore ``excview`` is never executed. This is one of the major differences between specifying the ``use_tweens=True`` and ``use_tweens=False`` arguments to -- cgit v1.2.3 From db2a03786ec76f2c6b7eaebb6f1b7c8b844d8c82 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 16 Sep 2012 22:32:26 -0400 Subject: make use_tweens=False the default --- docs/narr/subrequest.rst | 63 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 43876b45a..89551ab35 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -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 @@ -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 @@ -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` @@ -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 @@ -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): @@ -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 @@ -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 @@ -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. @@ -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 -- cgit v1.2.3 From 043ccddb909327106264d10ed5d413760a51770d Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 2 Jan 2013 02:22:52 +0200 Subject: eliminate other repeated words --- docs/narr/subrequest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 89551ab35..b5bc5ec48 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -142,7 +142,7 @@ 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 +arguments: a positional argument ``request`` that must be provided, and ``use_tweens`` keyword argument that is optional; it defaults to ``False``. The ``request`` object passed to the API must be an object that implements -- cgit v1.2.3 From e3ed0ee85d3edc49740637e3bf76a04f1e6a6963 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 10 Feb 2013 13:31:12 +0200 Subject: use a more approriate Sphinx directive --- docs/narr/subrequest.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index b5bc5ec48..033f045a6 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -6,9 +6,7 @@ Invoking a Subrequest ===================== -.. warning:: - - This feature was added in Pyramid 1.4a1. +.. versionadded:: 1.4 :app:`Pyramid` allows you to invoke a subrequest at any point during the processing of a request. Invoking a subrequest allows you to obtain a -- cgit v1.2.3 From fe30a28c0ab6e6b3ad50893baf06316aa68bd48f Mon Sep 17 00:00:00 2001 From: Catalin Iacob Date: Sun, 31 Mar 2013 13:58:49 +0200 Subject: Remove extra word --- docs/narr/subrequest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 033f045a6..7c0c61d71 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -250,7 +250,7 @@ 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 :meth:`pyramid.request.Request.blank`. Once you've constructed a request -object, you'll need to massage the it to match the view callable you'd like +object, you'll need to massage it to match the view callable you'd like to be executed during the subrequest. This can be done by adjusting the subrequest's URL, its headers, its request method, and other attributes. The documentation for :class:`pyramid.request.Request` exposes the methods you -- cgit v1.2.3 From 1ad37b0891c92087d54255ab1ee9dd0f28b2c150 Mon Sep 17 00:00:00 2001 From: Catalin Iacob Date: Mon, 1 Apr 2013 17:54:22 +0200 Subject: Add missing word --- docs/narr/subrequest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 7c0c61d71..93ce747ee 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -155,7 +155,7 @@ In the example above, the call to 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 +configured instead of raising the exception. This is because exception views are called by the exception view :term:`tween` as described in :ref:`exception_views` when any view raises an exception. -- cgit v1.2.3 From f758ec6487bb3b57fb5b1c3aa9ac1f28930d6bd8 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Fri, 5 Apr 2013 00:00:44 +0200 Subject: fix some cross-references --- docs/narr/subrequest.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 93ce747ee..6437bd0fa 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -223,16 +223,16 @@ unconditionally: :meth:`~pyramid.config.Configurator.set_request_property`) on the subrequest object passed as ``request`` -- causes a :class:`~pyramid.event.NewRequest` event to be sent at the +- causes a :class:`~pyramid.events.NewRequest` event to be sent at the beginning of request processing. -- causes a :class:`~pyramid.event.ContextFound` event to be sent when a +- causes a :class:`~pyramid.events.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 +- causes a :class:`~pyramid.events.NewResponse` event to be sent when the Pyramid application returns a response. - Calls any :term:`response callback` functions defined within the subrequest's -- cgit v1.2.3 From fc477b2e4b20ae2788e468e45b2831e774be8ced Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 7 Sep 2013 21:59:41 -0400 Subject: - The ``pyramid.events.NewResponse`` event is now sent **after** response callbacks are executed. It previously executed before response callbacks were executed. Rationale: it's more useful to be able to inspect the response after response callbacks have done their jobs instead of before. Closes #1116. --- docs/narr/subrequest.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 6437bd0fa..4b4e99d41 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -232,12 +232,12 @@ unconditionally: - Ensures that the user implied by the request passed has the necessary authorization to invoke view callable before calling it. -- causes a :class:`~pyramid.events.NewResponse` event to be sent when the - Pyramid application returns a response. - - Calls any :term:`response callback` functions defined within the subrequest's lifetime if a response is obtained from the Pyramid application. +- causes a :class:`~pyramid.events.NewResponse` event to be sent if a response + is obtained. + - Calls any :term:`finished callback` functions defined within the subrequest's lifetime. -- cgit v1.2.3 From f3d20e19807bc1a86acccdd74cff10698d249350 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 28 Oct 2015 23:42:12 -0700 Subject: minor grammar, rewrap 79 columns, some .rst syntax fixes, add a header and index entry --- docs/narr/subrequest.rst | 152 ++++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 4b4e99d41..13b00efb6 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -41,23 +41,22 @@ Here's an example application which uses a subrequest: server = make_server('0.0.0.0', 8080, app) server.serve_forever() -When ``/view_one`` is visted in a browser, the text printed in the browser -pane will be ``This came from view_two``. The ``view_one`` view used the -:meth:`pyramid.request.Request.invoke_subrequest` API to obtain a response -from another view (``view_two``) within the same application when it -executed. It did so by constructing a new request that had a URL that it -knew would match the ``view_two`` view registration, and passed that new -request along to :meth:`pyramid.request.Request.invoke_subrequest`. The -``view_two`` view callable was invoked, and it returned a response. The -``view_one`` view callable then simply returned the response it obtained from -the ``view_two`` view callable. +When ``/view_one`` is visted in a browser, the text printed in the browser pane +will be ``This came from view_two``. The ``view_one`` view used the +:meth:`pyramid.request.Request.invoke_subrequest` API to obtain a response from +another view (``view_two``) within the same application when it executed. It +did so by constructing a new request that had a URL that it knew would match +the ``view_two`` view registration, and passed that new request along to +:meth:`pyramid.request.Request.invoke_subrequest`. The ``view_two`` view +callable was invoked, and it returned a response. The ``view_one`` view +callable then simply returned the response it obtained from 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 renderer or which returns an object that can be interpreted by a response adapter when found and invoked via -:meth:`pyramid.request.Request.invoke_subrequest` will return a Response -object: +:meth:`pyramid.request.Request.invoke_subrequest` will return a Response object: .. code-block:: python @@ -83,19 +82,19 @@ object: server = make_server('0.0.0.0', 8080, app) server.serve_forever() -Even though the ``view_two`` view callable returned a string, it was invoked -in such a way that the ``string`` renderer associated with the view -registration that was found turned it into a "real" response object for -consumption by ``view_one``. +Even though the ``view_two`` view callable returned a string, it was invoked in +such a way that the ``string`` renderer associated with the view registration +that was found turned it into a "real" response object for consumption by +``view_one``. Being able to unconditionally obtain a response object by invoking a view callable indirectly is the main advantage to using -:meth:`pyramid.request.Request.invoke_subrequest` instead of simply importing -a view callable and executing it directly. Note that there's not much -advantage to invoking a view using a subrequest if you *can* invoke a view -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. +:meth:`pyramid.request.Request.invoke_subrequest` instead of simply importing a +view callable and executing it directly. Note that there's not much advantage +to invoking a view using a subrequest if you *can* invoke a view 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, by default, if a view callable invoked by a subrequest raises an exception, the exception will be raised to the caller of @@ -136,15 +135,21 @@ 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. +generated. We can change this behavior; how to do so is described below in our +discussion of the ``use_tweens`` argument. + +.. index:: + pair: subrequest; use_tweens + +Subrequests with Tweens +----------------------- The :meth:`pyramid.request.Request.invoke_subrequest` API accepts two -arguments: a positional argument ``request`` that must be provided, and -``use_tweens`` keyword argument that is optional; it defaults to ``False``. +arguments: a required positional argument ``request``, and an optional keyword +argument ``use_tweens`` which 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` +The ``request`` object passed to the API must be an object that implements the +Pyramid request interface (such as a :class:`pyramid.request.Request` instance). If ``use_tweens`` is ``True``, the request will be sent to the :term:`tween` in the tween stack closest to the request ingress. If ``use_tweens`` is ``False``, the request will be sent to the main router @@ -153,9 +158,9 @@ handler, and no tweens will be invoked. In the example above, 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 is because exception views +which is ``False``. Alternatively, you can pass ``use_tweens=True`` to ensure +that it will convert an exception to a Response if an :term:`exception view` is +configured, instead of raising the exception. This is because exception views are called by the exception view :term:`tween` as described in :ref:`exception_views` when any view raises an exception. @@ -199,71 +204,70 @@ 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 +This is one of the major differences between specifying the ``use_tweens=True`` +and ``use_tweens=False`` arguments to :meth:`~pyramid.request.Request.invoke_subrequest`. ``use_tweens=True`` may -also imply invoking transaction commit/abort for the logic executed in the -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 +also imply invoking a transaction commit or abort for the logic executed in the +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 -unconditionally: - -- manages the threadlocal stack so that +unconditionally does the following: + +- It manages the threadlocal stack so that :func:`~pyramid.threadlocal.get_current_request` and - :func:`~pyramid.threadlocal.get_current_registry` work during a request - (they will return the subrequest instead of the original request) + :func:`~pyramid.threadlocal.get_current_registry` work during a request (they + will return the subrequest instead of the original request). -- Adds a ``registry`` attribute and a ``invoke_subrequest`` attribute (a - callable) to the request object it's handed. +- It adds a ``registry`` attribute and an ``invoke_subrequest`` attribute (a + callable) to the request object to which it is handed. -- sets request extensions (such as those added via +- It sets request extensions (such as those added via :meth:`~pyramid.config.Configurator.add_request_method` or :meth:`~pyramid.config.Configurator.set_request_property`) on the subrequest - object passed as ``request`` + object passed as ``request``. -- causes a :class:`~pyramid.events.NewRequest` event to be sent at the +- It causes a :class:`~pyramid.events.NewRequest` event to be sent at the beginning of request processing. -- causes a :class:`~pyramid.events.ContextFound` event to be sent when a +- It causes a :class:`~pyramid.events.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. +- It ensures that the user implied by the request passed in has the necessary + authorization to invoke the view callable before calling it. -- Calls any :term:`response callback` functions defined within the subrequest's - lifetime if a response is obtained from the Pyramid application. +- It calls any :term:`response callback` functions defined within the + subrequest's lifetime if a response is obtained from the Pyramid application. -- causes a :class:`~pyramid.events.NewResponse` event to be sent if a response - is obtained. +- It causes a :class:`~pyramid.events.NewResponse` event to be sent if a + response is obtained. -- Calls any :term:`finished callback` functions defined within the subrequest's - lifetime. +- It 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 +The invocation of a subrequest has more or less exactly the same effect as the +invocation of a request received by the :app:`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 +:meth:`~pyramid.request.Request.invoke_subrequest`. You should construct a new +request instead as demonstrated in the above example, using :meth:`pyramid.request.Request.blank`. Once you've constructed a request -object, you'll need to massage it to match the view callable you'd like -to be executed during the subrequest. This can be done by adjusting the +object, you'll need to massage it to match the view callable that you'd like to +be executed during the subrequest. This can be done by adjusting the subrequest's URL, its headers, its request method, and other attributes. The documentation for :class:`pyramid.request.Request` exposes the methods you -should call and attributes you should set on the request you create to -massage it into something that will actually match the view you'd like to -call via a subrequest. - -We've demonstrated use of a subrequest from within a view callable, but you -can use the :meth:`~pyramid.request.Request.invoke_subrequest` API from -within a tween or an event handler as well. It's usually a poor idea to -invoke :meth:`~pyramid.request.Request.invoke_subrequest` from within a -tween, because tweens already by definition have access to a function that -will cause a subrequest (they are passed a ``handle`` function), but you can -do it. It's fine to invoke -:meth:`~pyramid.request.Request.invoke_subrequest` from within an event -handler, however. +should call and attributes you should set on the request that you create, then +massage it into something that will actually match the view you'd like to call +via a subrequest. + +We've demonstrated use of a subrequest from within a view callable, but you can +use the :meth:`~pyramid.request.Request.invoke_subrequest` API from within a +tween or an event handler as well. Even though you can do it, it's usually a +poor idea to invoke :meth:`~pyramid.request.Request.invoke_subrequest` from +within a tween, because tweens already, by definition, have access to a +function that will cause a subrequest (they are passed a ``handle`` function). +It's fine to invoke :meth:`~pyramid.request.Request.invoke_subrequest` from +within an event handler, however. -- cgit v1.2.3 From 33b89f5853aef30dfe4546083c62735ed3f96ef4 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 30 Oct 2015 01:06:30 -0700 Subject: add linenos and emphasize-lines to code examples --- docs/narr/subrequest.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 13b00efb6..02ae14aa5 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -17,6 +17,7 @@ application. Here's an example application which uses a subrequest: .. code-block:: python + :linenos: from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -56,9 +57,12 @@ 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 renderer or which returns an object that can be interpreted by a response adapter when found and invoked via -:meth:`pyramid.request.Request.invoke_subrequest` will return a Response object: +:meth:`pyramid.request.Request.invoke_subrequest` will return a Response +object: .. code-block:: python + :linenos: + :emphasize-lines: 11 from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -102,6 +106,8 @@ exception, the exception will be raised to the caller of :term:`exception view` configured: .. code-block:: python + :linenos: + :emphasize-lines: 11-16 from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -169,6 +175,8 @@ We can cause the subrequest to be run through the tween stack by passing :meth:`~pyramid.request.Request.invoke_subrequest`, like this: .. code-block:: python + :linenos: + :emphasize-lines: 7 from wsgiref.simple_server import make_server from pyramid.config import Configurator -- cgit v1.2.3 From 65bb52bafa5d44b378f01dfb47816a952bf93a66 Mon Sep 17 00:00:00 2001 From: Svintsov Dmitry Date: Sun, 24 Jan 2016 16:36:43 +0500 Subject: fix indent in docs --- docs/narr/subrequest.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 02ae14aa5..daa3cc43f 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -17,7 +17,7 @@ application. Here's an example application which uses a subrequest: .. code-block:: python - :linenos: + :linenos: from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -61,8 +61,8 @@ adapter when found and invoked via object: .. code-block:: python - :linenos: - :emphasize-lines: 11 + :linenos: + :emphasize-lines: 11 from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -106,8 +106,8 @@ exception, the exception will be raised to the caller of :term:`exception view` configured: .. code-block:: python - :linenos: - :emphasize-lines: 11-16 + :linenos: + :emphasize-lines: 11-16 from wsgiref.simple_server import make_server from pyramid.config import Configurator @@ -175,8 +175,8 @@ We can cause the subrequest to be run through the tween stack by passing :meth:`~pyramid.request.Request.invoke_subrequest`, like this: .. code-block:: python - :linenos: - :emphasize-lines: 7 + :linenos: + :emphasize-lines: 7 from wsgiref.simple_server import make_server from pyramid.config import Configurator -- cgit v1.2.3 From 542f86ba5cd3e2eec18224b2e4eff88fe58b6f43 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 14:20:26 -0500 Subject: add a new docs section on invoking exception views --- docs/narr/subrequest.rst | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index daa3cc43f..ae1dd1b91 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -279,3 +279,49 @@ within a tween, because tweens already, by definition, have access to a function that will cause a subrequest (they are passed a ``handle`` function). It's fine to invoke :meth:`~pyramid.request.Request.invoke_subrequest` from within an event handler, however. + +Invoking an Exception View +-------------------------- + +.. versionadded:: 1.7 + +:app:`Pyramid` apps may define a :term:`exception views ` which +can handle any raised exceptions that escape from your code while processing +a request. By default, an unhandled exception will be caught by the `EXCVIEW` +:term:`tween` which will then lookup an exception view that can handle the +exception type, generating an appropriate error response. + +In :app:`Pyramid` 1.7 the :meth:`pyramid.request.Request.invoke_exception_view` +was introduced which allows a user to invoke an exception view while manually +handling an exception. This can be useful in a few different circumstances: + +- Manually handling an exception losing the current call stack / flow. + +- Handling exceptions outside of the context of the `EXCVIEW` tween. The + tween only covers certain parts of the request processing pipeline + (See :ref:`router chapter`) and there are some corner cases where an + exception can be raised which will still bubble up to middleware and possibly + to the web server where a generic ``500 Internal Server Error`` will be + returned to the client. + +Below is an example usage of +:meth:`pyramid.request.Request.invoke_exception_view`: + +.. code-block:: python + :linenos: + + def foo(request): + try: + some_func_that_errors() + return response + except Exception: + response = request.invoke_exception_view() + # there is no exception view for this exception, simply + # re-raise and let someone else handle it + if response is not None: + return response + else: + raise + +Please note that in most cases you do not need to write code like this an may +rely on the `EXCVIEW` tween to handle this for you. -- cgit v1.2.3 From 78cf75aef700f2db65d3dac379811c7f17eab1f7 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 14:28:18 -0500 Subject: fix broken ref --- docs/narr/subrequest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index ae1dd1b91..60972b156 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -299,7 +299,7 @@ handling an exception. This can be useful in a few different circumstances: - Handling exceptions outside of the context of the `EXCVIEW` tween. The tween only covers certain parts of the request processing pipeline - (See :ref:`router chapter`) and there are some corner cases where an + (See :ref:`router_chapter`) and there are some corner cases where an exception can be raised which will still bubble up to middleware and possibly to the web server where a generic ``500 Internal Server Error`` will be returned to the client. -- cgit v1.2.3 From 7175a51bec9491ff58a8ef3a94cc7804b476541d Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 14:32:14 -0500 Subject: move comment closer to relevant logic --- docs/narr/subrequest.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 60972b156..a943dca5d 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -316,11 +316,11 @@ Below is an example usage of return response except Exception: response = request.invoke_exception_view() - # there is no exception view for this exception, simply - # re-raise and let someone else handle it if response is not None: return response else: + # there is no exception view for this exception, simply + # re-raise and let someone else handle it raise Please note that in most cases you do not need to write code like this an may -- cgit v1.2.3 From dc3f79537f6901cf81a25f557c8d7bad1fe4f111 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 14 Mar 2016 13:56:08 -0700 Subject: polish Invoking an Exception View docs - add index entry - minor grammar, syntax --- docs/narr/subrequest.rst | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'docs/narr/subrequest.rst') diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index a943dca5d..7c847de50 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -280,28 +280,32 @@ function that will cause a subrequest (they are passed a ``handle`` function). It's fine to invoke :meth:`~pyramid.request.Request.invoke_subrequest` from within an event handler, however. + +.. index:: + pair: subrequest; exception view + Invoking an Exception View -------------------------- .. versionadded:: 1.7 -:app:`Pyramid` apps may define a :term:`exception views ` which +:app:`Pyramid` apps may define :term:`exception views ` which can handle any raised exceptions that escape from your code while processing -a request. By default, an unhandled exception will be caught by the `EXCVIEW` -:term:`tween` which will then lookup an exception view that can handle the +a request. By default an unhandled exception will be caught by the ``EXCVIEW`` +:term:`tween`, which will then lookup an exception view that can handle the exception type, generating an appropriate error response. In :app:`Pyramid` 1.7 the :meth:`pyramid.request.Request.invoke_exception_view` -was introduced which allows a user to invoke an exception view while manually +was introduced, allowing a user to invoke an exception view while manually handling an exception. This can be useful in a few different circumstances: -- Manually handling an exception losing the current call stack / flow. +- Manually handling an exception losing the current call stack or flow. -- Handling exceptions outside of the context of the `EXCVIEW` tween. The - tween only covers certain parts of the request processing pipeline - (See :ref:`router_chapter`) and there are some corner cases where an - exception can be raised which will still bubble up to middleware and possibly - to the web server where a generic ``500 Internal Server Error`` will be +- Handling exceptions outside of the context of the ``EXCVIEW`` tween. The + tween only covers certain parts of the request processing pipeline (See + :ref:`router_chapter`). There are also some corner cases where an exception + can be raised that will still bubble up to middleware, and possibly to the + web server in which case a generic ``500 Internal Server Error`` will be returned to the client. Below is an example usage of @@ -323,5 +327,5 @@ Below is an example usage of # re-raise and let someone else handle it raise -Please note that in most cases you do not need to write code like this an may -rely on the `EXCVIEW` tween to handle this for you. +Please note that in most cases you do not need to write code like this, and you +may rely on the ``EXCVIEW`` tween to handle this for you. -- cgit v1.2.3