From dc7122f8bb5033d0cd0e95f5adfa66c4499f140e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 6 Aug 2011 17:41:30 -0400 Subject: add glossary entry for tween --- docs/glossary.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index c6705fdc5..ccb62bbc8 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -917,3 +917,14 @@ Glossary PyPy is an "alternative implementation of the Python language":http://pypy.org/ + tween + A bit of code that sits between the Pyramid router's main request + handling function and the upstream WSGI component that uses + :app:`Pyramid` as its 'app'. A tween may be used by Pyramid framework + extensions, to provide, for example, Pyramid-specific view timing + support bookkeeping code that examines exceptions before they are + returned to the upstream WSGI application. Tweens behave a bit like + :mod:`WSGI` 'middleware' but they have the benefit of running in a + context in which they have access to the Pyramid :term:`application + registry` as well as the Pyramid rendering machinery. + -- cgit v1.2.3 From 1311321d454ded6226b09f929ebc9e4aa2c12771 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 6 Aug 2011 18:58:26 -0400 Subject: add tweens module, add docs for ptweens and tweens to hooks --- docs/api.rst | 1 + docs/api/config.rst | 2 +- docs/api/tweens.rst | 8 +++ docs/narr/commandline.rst | 75 ++++++++++++++++++++++++++- docs/narr/hooks.rst | 128 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 docs/api/tweens.rst (limited to 'docs') diff --git a/docs/api.rst b/docs/api.rst index a7e1566d3..6ff6e9fb1 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -32,6 +32,7 @@ documentation is organized alphabetically by module name. api/testing api/threadlocal api/traversal + api/tweens api/url api/view api/wsgi diff --git a/docs/api/config.rst b/docs/api/config.rst index 21e2b828d..1a9bb6ba4 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -78,7 +78,7 @@ .. automethod:: set_view_mapper - .. automethod:: add_request_handler + .. automethod:: add_tween .. automethod:: testing_securitypolicy diff --git a/docs/api/tweens.rst b/docs/api/tweens.rst new file mode 100644 index 000000000..5fc15cb00 --- /dev/null +++ b/docs/api/tweens.rst @@ -0,0 +1,8 @@ +.. _tweens_module: + +:mod:`pyramid.tweens` +--------------------- + +.. automodule:: pyramid.tweens + + .. autofunction:: excview_tween_factory diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 509af7dd3..6f969196f 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -297,8 +297,79 @@ application, nothing will be printed to the console when ``paster proutes`` is executed. .. index:: - single: scripting - single: bootstrap + pair: tweens; printing + single: paster ptweens + single: ptweens + +.. _displaying_tweens: + +Displaying "Tweens" +------------------- + +A user can get a representation of both the implicit :term:`tween` ordering +(the ordering specified by calls to +:meth:`pyramid.config.Configurator.add_tween`) and the explicit tween +ordering (specified by the ``pyramid.tweens`` configuration setting) +orderings using the ``paster ptweens`` command. Handler factories which are +functions or classes will show up as a standard Python dotted name in the +``paster ptweens`` output. Tween factories which are *instances* will show +their module and class name; the Python object id of the instance will be +appended. + +For example, here's the ``paster pwteens`` command run against a system +configured without any explicit tweens: + +.. code-block:: text + :linenos: + + [chrism@thinko starter]$ ../bin/paster ptweens development.ini + "pyramid.tweens" config value NOT set (implicitly ordered tweens used) + + Position Name + -------- ---- + 0 pyramid.router.excview_tween_factory + +Here's the ``paster pwteens`` command run against a system configured *with* +explicit tweens defined in its ``development.ini`` file: + +.. code-block:: text + :linenos: + + [chrism@thinko starter]$ ../bin/paster ptweens development.ini + "pyramid.tweens" config value set (explicitly ordered tweens used) + + Explicit Tween Chain (used) + + Position Name + -------- ---- + 0 pyramid.tweens.excview_tween_factory + 1 starter.tween_factory1 + 2 starter.tween_factory2 + + Implicit Tween Chain (not used) + + Position Name + -------- ---- + 0 pyramid.tweens.excview_tween_factory + +Here's the application configuration section of the ``development.ini`` used +by the above ``paster ptweens`` command which reprorts that the explicit +tween chain is used: + +.. code-block:: text + :linenos: + + [app:starter] + use = egg:starter + pyramid.reload_templates = true + pyramid.debug_authorization = false + pyramid.debug_notfound = false + pyramid.debug_routematch = false + pyramid.debug_templates = true + pyramid.default_locale_name = en + pyramid.tweens = pyramid.tweens.excview_tween_factory + starter.tween_factory1 + starter.tween_factory2 .. _writing_a_script: diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 4f493c854..7290876e6 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -828,3 +828,131 @@ performed, enabling you to set up the utility in advance: For full details, please read the `Venusian documentation `_. +.. _registering_tweens: + +Registering "Tweens" +-------------------- + +.. note:: Tweens are a feature which were added in Pyramid 1.1.1. They are + not available in any previous version. + +A :term:`tween` (think: "between") is a bit of code that sits between the +Pyramid router's main request handling function and the upstream WSGI +component that uses :app:`Pyramid` as its "app". This is a feature that may +be used by Pyramid framework extensions, to provide, for example, +Pyramid-specific view timing support bookkeeping code that examines +exceptions before they are returned to the upstream WSGI application. Tweens +behave a bit like :term:`WSGI` middleware but they have the benefit of +running in a context in which they have access to the Pyramid +:term:`application registry` as well as the Pyramid rendering machinery. + +To make use of tweens, you must construct a "tween factory". A tween factory +must be a callable (or a :term:`dotted Python name` to such a callable) which +accepts two arguments: ``handler`` and ``registry``. ``handler`` will be the +either the main Pyramid request handling function or another tween (if more +than one tween is configured into the request handling chain). ``registry`` +will be the Pyramid :term:`application registry` represented by this +Configurator. A tween factory must return a tween when it is called. + +A tween is a callable which accepts a :term:`request` object and returns a +two-tuple consisting of a :term:`request` object and a :term:`response` +object. + +Once you've created a tween factory, you can register it using the +:meth:`pyramid.config.Configurator.add_tween` method. + +Here's an example creating a tween factory and registering it: + +.. code-block:: python + :lineno: + + import time + from pyramid.settings import asbool + import logging + + log = logging.getLogger(__name__) + + def timing_tween_factory(handler, registry): + if asbool(registry.settings.get('do_timing')): + # if timing support is enabled, return a wrapper + def timing_tween(request): + start = time.time() + try: + request, response = handler(request) + finally: + end = time.time() + log.debug('The request took %s seconds' % + (end - start)) + return request, response + return timing_tween + # if timing support is not enabled, return the original + # handler + return handler + + from pyramid.config import Configurator + + config = Configurator() + config.add_tween(timing_tween_factory) + +The ``request`` argument to a tween will be the request created by Pyramid's +router when it receives a WSGI request. + +If more than one call to :meth:`pyramid.config.Configurator.add_tween` is +made within a single application configuration, the added tweens will be +chained together. The first tween factory added will be called with the +default Pyramid request handler as its ``handler`` argument, the second tween +factory added will be called with the result of the first tween factory as +its ``handler`` argument, and so on, ad infinitum. The Pyramid router will +use the outermost tween produced by this chain (the tween generated by the +very last tween factory added) as its request handler function. + +Pyramid will prevent the same tween factory from being added to the implicit +tween chain more than once using configuration conflict detection. If you +wish to add the same tween factory more than once in a configuration, you +should either: a) use a tween factory that is an instance rather than a +function or class, b) use a function or class as a tween factory with the +same logic as the other tween factory it conflicts with but with a different +``__name__`` attribute or c) call :meth:`pyramid.config.Configurator.commit` +between calls to :meth:`pyramid.config.Configurator.add_tween`. + +By default, the ordering of the chain is controlled entirely by the relative +ordering of calls to :meth:`pyramid.config.Configurator.add_tween`. However, +the deploying user can override tween inclusion and ordering entirely in his +Pyramid configuration using the ``pyramid.tweens`` settings value. When +used, this settings value will be a list of Python dotted names which imply +the ordering (and inclusion) of tween factories in the tween chain. For +example: + +.. code-block:: ini + :linenos: + + [app:main] + use = egg:MyApp + pyramid.reload_templates = true + pyramid.debug_authorization = false + pyramid.debug_notfound = false + pyramid.debug_routematch = false + pyramid.debug_templates = true + pyramid.tweens = pyramid.tweens.excview_tween_factory + myapp.my_cool_tween_factory + +In the above configuration, calls made during configuration to +:meth:`pyramid.config.Configurator.add_tween` are ignored, and the user is +telling the system to use the tween factories he has listed in the +``pyramid.tweens`` configuration setting (each is a:term:`Python dotted name` +which points to a tween factory). The *last* tween factory in the +``pyramid.tweens`` list will be used as the producer of the effective +:app:`Pyramid` request handling function; it will wrap the tween factory +declared directly "above" it, ad infinitum. + +.. note:: Pyramid's own :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. + +The ``paster ptweens`` command-line utility can be used to report the current +tween chain used by an application. See :ref:`displaying_tweens`. + -- cgit v1.2.3 From 8d1533d95ceebbef641a220236b77d9b3931cc31 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 6 Aug 2011 20:22:43 -0400 Subject: change return value of tween to just response --- docs/narr/hooks.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 7290876e6..c6438dfdf 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -855,8 +855,7 @@ will be the Pyramid :term:`application registry` represented by this Configurator. A tween factory must return a tween when it is called. A tween is a callable which accepts a :term:`request` object and returns a -two-tuple consisting of a :term:`request` object and a :term:`response` -object. +two-tuple a :term:`response` object. Once you've created a tween factory, you can register it using the :meth:`pyramid.config.Configurator.add_tween` method. @@ -878,12 +877,12 @@ Here's an example creating a tween factory and registering it: def timing_tween(request): start = time.time() try: - request, response = handler(request) + response = handler(request) finally: end = time.time() log.debug('The request took %s seconds' % (end - start)) - return request, response + return response return timing_tween # if timing support is not enabled, return the original # handler -- cgit v1.2.3 From 18a99ae15e7f36cd21da6e2d2e70d61d1733bf30 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 6 Aug 2011 20:35:34 -0400 Subject: docs rendering --- docs/narr/hooks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index c6438dfdf..889e8d6d8 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -863,7 +863,7 @@ Once you've created a tween factory, you can register it using the Here's an example creating a tween factory and registering it: .. code-block:: python - :lineno: + :linenos: import time from pyramid.settings import asbool -- cgit v1.2.3