Steve Piercy
2015-11-03 5fa4e31e028b284b8a74ca5ffbdb65c23047b453
minor grammar, fix .rst markup, rewrap to 79 columns
(cherry picked from commit 8aa1c2a)
1 files modified
638 ■■■■ changed files
docs/narr/hooks.rst 638 ●●●● patch | view | raw | blame | history
docs/narr/hooks.rst
@@ -14,12 +14,12 @@
Changing the Not Found View
---------------------------
When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not
Found View`, which is a :term:`view callable`. The default Not Found View
can be overridden through application configuration.
When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not Found
View`, which is a :term:`view callable`. The default Not Found View can be
overridden through application configuration.
If your application uses :term:`imperative configuration`, you can replace
the Not Found View by using the
If your application uses :term:`imperative configuration`, you can replace the
Not Found View by using the
:meth:`pyramid.config.Configurator.add_notfound_view` method:
.. code-block:: python
@@ -77,14 +77,14 @@
      config = Configurator()
      config.scan()
The ``notfound_get`` view will be called when a view could not be found and
the request method was ``GET``.  The ``notfound_post`` view will be called
when a view could not be found and the request method was ``POST``.
The ``notfound_get`` view will be called when a view could not be found and the
request method was ``GET``.  The ``notfound_post`` view will be called when a
view could not be found and the request method was ``POST``.
Like any other view, the Not Found View must accept at least a ``request``
parameter, or both ``context`` and ``request``.  The ``request`` is the
current :term:`request` representing the denied action.  The ``context`` (if
used in the call signature) will be the instance of the
parameter, or both ``context`` and ``request``.  The ``request`` is the current
:term:`request` representing the denied action.  The ``context`` (if used in
the call signature) will be the instance of the
:exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the view to
be called.
@@ -106,13 +106,13 @@
.. note::
   When a Not Found View callable is invoked, it is passed a
   :term:`request`.  The ``exception`` attribute of the request will be an
   instance of the :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that
   caused the Not Found View to be called.  The value of
   ``request.exception.message`` will be a value explaining why the Not Found
   error was raised.  This message has different values depending whether the
   ``pyramid.debug_notfound`` environment setting is true or false.
   When a Not Found View callable is invoked, it is passed a :term:`request`.
   The ``exception`` attribute of the request will be an instance of the
   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the Not
   Found View to be called.  The value of ``request.exception.message`` will be
   a value explaining why the Not Found exception was raised.  This message has
   different values depending on whether the ``pyramid.debug_notfound``
   environment setting is true or false.
.. note::
@@ -124,9 +124,9 @@
.. warning::
   When a Not Found View callable accepts an argument list as
   described in :ref:`request_and_context_view_definitions`, the ``context``
   passed as the first argument to the view callable will be the
   When a Not Found View callable accepts an argument list as described in
   :ref:`request_and_context_view_definitions`, the ``context`` passed as the
   first argument to the view callable will be the
   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance.  If
   available, the resource context will still be available as
   ``request.context``.
@@ -140,13 +140,13 @@
---------------------------
When :app:`Pyramid` can't authorize execution of a view based on the
:term:`authorization policy` in use, it invokes a :term:`forbidden view`.
The default forbidden response has a 403 status code and is very plain, but
the view which generates it can be overridden as necessary.
:term:`authorization policy` in use, it invokes a :term:`forbidden view`. The
default forbidden response has a 403 status code and is very plain, but the
view which generates it can be overridden as necessary.
The :term:`forbidden view` callable is a view callable like any other.  The
:term:`view configuration` which causes it to be a "forbidden" view consists
of using the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the
:term:`view configuration` which causes it to be a "forbidden" view consists of
using the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the
:class:`pyramid.view.forbidden_view_config` decorator.
For example, you can add a forbidden view by using the
@@ -181,14 +181,11 @@
      config.scan()
Like any other view, the forbidden view must accept at least a ``request``
parameter, or both ``context`` and ``request``.  If a forbidden view
callable accepts both ``context`` and ``request``, the HTTP Exception is passed
as context. The ``context`` as found by the router when view was
denied (that you normally would expect) is available as
``request.context``.  The ``request`` is the  current :term:`request`
representing the denied action.
parameter, or both ``context`` and ``request``.  If a forbidden view callable
accepts both ``context`` and ``request``, the HTTP Exception is passed as
context. The ``context`` as found by the router when the view was denied (which
you normally would expect) is available as ``request.context``.  The
``request`` is the  current :term:`request` representing the denied action.
Here's some sample code that implements a minimal forbidden view:
@@ -203,15 +200,15 @@
.. note::
   When a forbidden view callable is invoked, it is passed a
   :term:`request`.  The ``exception`` attribute of the request will be an
   instance of the :exc:`~pyramid.httpexceptions.HTTPForbidden` exception
   that caused the forbidden view to be called.  The value of
   ``request.exception.message`` will be a value explaining why the forbidden
   was raised and ``request.exception.result`` will be extended information
   about the forbidden exception.  These messages have different values
   depending whether the ``pyramid.debug_authorization`` environment setting
   is true or false.
   When a forbidden view callable is invoked, it is passed a :term:`request`.
   The ``exception`` attribute of the request will be an instance of the
   :exc:`~pyramid.httpexceptions.HTTPForbidden` exception that caused the
   forbidden view to be called.  The value of ``request.exception.message``
   will be a value explaining why the forbidden exception was raised, and
   ``request.exception.result`` will be extended information about the
   forbidden exception.  These messages have different values depending on
   whether the ``pyramid.debug_authorization`` environment setting is true or
   false.
.. index::
   single: request factory
@@ -223,11 +220,11 @@
Whenever :app:`Pyramid` handles a request from a :term:`WSGI` server, it
creates a :term:`request` object based on the WSGI environment it has been
passed.  By default, an instance of the :class:`pyramid.request.Request`
class is created to represent the request object.
passed.  By default, an instance of the :class:`pyramid.request.Request` class
is created to represent the request object.
The class (aka "factory") that :app:`Pyramid` uses to create a request object
instance can be changed by passing a ``request_factory`` argument to the
The class (a.k.a., "factory") that :app:`Pyramid` uses to create a request
object instance can be changed by passing a ``request_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.
@@ -242,7 +239,7 @@
   config = Configurator(request_factory=MyRequest)
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
already constructed a :term:`configurator`, it can also be registered via the
:meth:`pyramid.config.Configurator.set_request_factory` method:
.. code-block:: python
@@ -262,19 +259,19 @@
.. _adding_request_method:
Adding Methods or Properties to Request Object
----------------------------------------------
Adding Methods or Properties to a Request Object
------------------------------------------------
.. versionadded:: 1.4.
Since each Pyramid application can only have one :term:`request` factory,
:ref:`changing the request factory <changing_the_request_factory>`
is not that extensible, especially if you want to build composable features
(e.g., Pyramid add-ons and plugins).
:ref:`changing the request factory <changing_the_request_factory>` is not that
extensible, especially if you want to build composable features (e.g., Pyramid
add-ons and plugins).
A lazy property can be registered to the request object via the
:meth:`pyramid.config.Configurator.add_request_method` API. This allows you
to specify a callable that will be available on the request object, but will not
:meth:`pyramid.config.Configurator.add_request_method` API. This allows you to
specify a callable that will be available on the request object, but will not
actually execute the function until accessed.
.. warning::
@@ -298,9 +295,10 @@
   config.add_request_method(total)
   config.add_request_method(prop, reify=True)
In the above example, ``total`` is added as a method. However, ``prop`` is added
as a property and its result is cached per-request by setting ``reify=True``.
This way, we eliminate the overhead of running the function multiple times.
In the above example, ``total`` is added as a method. However, ``prop`` is
added as a property and its result is cached per-request by setting
``reify=True``. This way, we eliminate the overhead of running the function
multiple times.
   >>> request.total(1, 2, 3)
   6
@@ -354,18 +352,18 @@
.. _changing_the_response_factory:
Changing the Response Factory
-------------------------------
-----------------------------
.. versionadded:: 1.6
Whenever :app:`Pyramid` returns a response from a view it creates a
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 factory that :app:`Pyramid` uses to create a response object instance can be
changed by passing a :class:`pyramid.interfaces.IResponseFactory` argument to
the constructor of the :term:`configurator`.  This argument can be either a
The factory that :app:`Pyramid` uses to create a response object instance can
be changed by passing a :class:`pyramid.interfaces.IResponseFactory` argument
to the constructor of the :term:`configurator`.  This argument can be either a
callable or a :term:`dotted Python name` representing a callable.
The factory takes a single positional argument, which is a :term:`Request`
@@ -381,8 +379,8 @@
   config = Configurator(response_factory=lambda r: 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
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
@@ -403,13 +401,13 @@
.. _beforerender_event:
Using The Before Render Event
Using the Before Render Event
-----------------------------
Subscribers to the :class:`pyramid.events.BeforeRender` event may introspect
and modify the set of :term:`renderer globals` before they are passed to a
:term:`renderer`.  This event object iself has a dictionary-like interface
that can be used for this purpose.  For example:
:term:`renderer`.  This event object iself has a dictionary-like interface that
can be used for this purpose.  For example:
.. code-block:: python
    :linenos:
@@ -421,22 +419,22 @@
    def add_global(event):
        event['mykey'] = 'foo'
An object of this type is sent as an event just before a :term:`renderer`
is invoked.
An object of this type is sent as an event just before a :term:`renderer` is
invoked.
If a subscriber attempts to add a key that already exist in the renderer
If a subscriber attempts to add a key that already exists in the renderer
globals dictionary, a :exc:`KeyError` is raised.  This limitation is enforced
because event subscribers do not possess any relative ordering.  The set of
keys added to the renderer globals dictionary by all
:class:`pyramid.events.BeforeRender` subscribers and renderer globals
factories must be unique.
:class:`pyramid.events.BeforeRender` subscribers and renderer globals factories
must be unique.
The dictionary returned from the view is accessible through the
:attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`
event.
Suppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from
your view callable, like so:
Suppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from your
view callable, like so:
.. code-block:: python
   :linenos:
@@ -492,24 +490,23 @@
           response.cache_control.max_age = 360
   request.add_response_callback(cache_callback)
No response callback is called if an unhandled exception happens in
application code, or if the response object returned by a :term:`view
callable` is invalid.  Response callbacks *are*, however, invoked when a
:term:`exception view` is rendered successfully: in such a case, the
:attr:`request.exception` attribute of the request when it enters a response
callback will be an exception object instead of its default value of
``None``.
No response callback is called if an unhandled exception happens in application
code, or if the response object returned by a :term:`view callable` is invalid.
Response callbacks *are*, however, invoked when a :term:`exception view` is
rendered successfully.  In such a case, the :attr:`request.exception` attribute
of the request when it enters a response callback will be an exception object
instead of its default value of ``None``.
Response callbacks are called in the order they're added
(first-to-most-recently-added).  All response callbacks are called *before*
the :class:`~pyramid.events.NewResponse` event is sent.  Errors raised by
response callbacks are not handled specially.  They will be propagated to the
caller of the :app:`Pyramid` router application.
(first-to-most-recently-added).  All response callbacks are called *before* the
:class:`~pyramid.events.NewResponse` event is sent.  Errors raised by response
callbacks are not handled specially.  They will be propagated to the caller of
the :app:`Pyramid` router application.
A response callback has a lifetime of a *single* request.  If you want a
response callback to happen as the result of *every* request, you must
re-register the callback into every new request (perhaps within a subscriber
of a :class:`~pyramid.events.NewRequest` event).
re-register the callback into every new request (perhaps within a subscriber of
a :class:`~pyramid.events.NewRequest` event).
.. index::
   single: finished callback
@@ -520,15 +517,15 @@
------------------------
A :term:`finished callback` is a function that will be called unconditionally
by the :app:`Pyramid` :term:`router` at the very end of request processing.
A finished callback can be used to perform an action at the end of a request
by the :app:`Pyramid` :term:`router` at the very end of request processing. A
finished callback can be used to perform an action at the end of a request
unconditionally.
The :meth:`pyramid.request.Request.add_finished_callback` method is used to
register a finished callback.
A finished callback is a callable which accepts a single positional
parameter: ``request``.  For example:
A finished callback is a callable which accepts a single positional parameter:
``request``.  For example:
.. code-block:: python
   :linenos:
@@ -543,29 +540,27 @@
   request.add_finished_callback(log_callback)
Finished callbacks are called in the order they're added
(first-to-most-recently-added).  Finished callbacks (unlike a
:term:`response callback`) are *always* called, even if an exception
happens in application code that prevents a response from being
generated.
(first-to-most-recently-added).  Finished callbacks (unlike a :term:`response
callback`) are *always* called, even if an exception happens in application
code that prevents a response from being generated.
The set of finished callbacks associated with a request are called *very
late* in the processing of that request; they are essentially the very last
thing called by the :term:`router` before a request "ends". They are called
after response processing has already occurred in a top-level ``finally:``
block within the router request processing code.  As a result, mutations
performed to the ``request`` provided to a finished callback will have no
meaningful effect, because response processing will have already occurred,
and the request's scope will expire almost immediately after all finished
callbacks have been processed.
The set of finished callbacks associated with a request are called *very late*
in the processing of that request; they are essentially the very last thing
called by the :term:`router` before a request "ends". They are called after
response processing has already occurred in a top-level ``finally:`` block
within the router request processing code.  As a result, mutations performed to
the ``request`` provided to a finished callback will have no meaningful effect,
because response processing will have already occurred, and the request's scope
will expire almost immediately after all finished callbacks have been
processed.
Errors raised by finished callbacks are not handled specially.  They
will be propagated to the caller of the :app:`Pyramid` router
application.
Errors raised by finished callbacks are not handled specially.  They will be
propagated to the caller of the :app:`Pyramid` router application.
A finished callback has a lifetime of a *single* request.  If you want a
finished callback to happen as the result of *every* request, you must
re-register the callback into every new request (perhaps within a subscriber
of a :class:`~pyramid.events.NewRequest` event).
re-register the callback into every new request (perhaps within a subscriber of
a :class:`~pyramid.events.NewRequest` event).
.. index::
   single: traverser
@@ -577,8 +572,8 @@
The default :term:`traversal` algorithm that :app:`Pyramid` uses is explained
in :ref:`traversal_algorithm`.  Though it is rarely necessary, this default
algorithm can be swapped out selectively for a different traversal pattern
via configuration.
algorithm can be swapped out selectively for a different traversal pattern via
configuration.
.. code-block:: python
   :linenos:
@@ -624,10 +619,10 @@
More than one traversal algorithm can be active at the same time.  For
instance, if your :term:`root factory` returns more than one type of object
conditionally, you could claim that an alternate traverser adapter is "for"
conditionally, you could claim that an alternative traverser adapter is "for"
only one particular class or interface.  When the root factory returned an
object that implemented that class or interface, a custom traverser would be
used.  Otherwise, the default traverser would be used.  For example:
used.  Otherwise the default traverser would be used.  For example:
.. code-block:: python
   :linenos:
@@ -639,13 +634,13 @@
   config.add_traverser(Traverser, MyRoot)
If the above stanza was added to a Pyramid ``__init__.py`` file's ``main``
function, :app:`Pyramid` would use the ``myapp.traversal.Traverser`` only
when the application :term:`root factory` returned an instance of the
function, :app:`Pyramid` would use the ``myapp.traversal.Traverser`` only when
the application :term:`root factory` returned an instance of the
``myapp.resources.MyRoot`` object.  Otherwise it would use the default
:app:`Pyramid` traverser to do traversal.
.. index::
   single: url generator
   single: URL generator
.. _changing_resource_url:
@@ -655,9 +650,8 @@
When you add a traverser as described in :ref:`changing_the_traverser`, it's
often convenient to continue to use the
:meth:`pyramid.request.Request.resource_url` API.  However, since the way
traversal is done will have been modified, the URLs it generates by default
may be incorrect when used against resources derived from your custom
traverser.
traversal is done will have been modified, the URLs it generates by default may
be incorrect when used against resources derived from your custom traverser.
If you've added a traverser, you can change how
:meth:`~pyramid.request.Request.resource_url` generates a URL for a specific
@@ -674,13 +668,13 @@
   config.add_resource_url_adapter(ResourceURLAdapter, MyRoot)
In the above example, the ``myapp.traversal.ResourceURLAdapter`` class will
be used to provide services to :meth:`~pyramid.request.Request.resource_url`
any time the :term:`resource` passed to ``resource_url`` is of the class
In the above example, the ``myapp.traversal.ResourceURLAdapter`` class will be
used to provide services to :meth:`~pyramid.request.Request.resource_url` any
time the :term:`resource` passed to ``resource_url`` is of the class
``myapp.resources.MyRoot``.  The ``resource_iface`` argument ``MyRoot``
represents the type of interface that must be possessed by the resource for
this resource url factory to be found.  If the ``resource_iface`` argument is
omitted, this resource url adapter will be used for *all* resources.
omitted, this resource URL adapter will be used for *all* resources.
The API that must be implemented by a class that provides
:class:`~pyramid.interfaces.IResourceURL` is as follows:
@@ -693,8 +687,8 @@
          resource
      """
      def __init__(self, resource, request):
          """ Accept the resource and request and set self.physical_path and
          self.virtual_path"""
          """ Accept the resource and request and set self.physical_path and
          self.virtual_path """
          self.virtual_path =  some_function_of(resource, request)
          self.physical_path =  some_other_function_of(resource, request)
@@ -703,7 +697,8 @@
<https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
:term:`Pylons` GitHub Pyramid repository.
See :meth:`pyramid.config.add_resource_url_adapter` for more information.
See :meth:`pyramid.config.Configurator.add_resource_url_adapter` for more
information.
.. index::
   single: IResponse
@@ -721,25 +716,24 @@
:meth:`pyramid.config.Configurator.add_response_adapter` or the
:class:`~pyramid.response.response_adapter` decorator.
Pyramid, in various places, adapts the result of calling a view callable to
the :class:`~pyramid.interfaces.IResponse` interface to ensure that the
object returned by the view callable is a "true" response object.  The vast
majority of time, the result of this adaptation is the result object itself,
as view callables written by "civilians" who read the narrative documentation
contained in this manual will always return something that implements the
:class:`~pyramid.interfaces.IResponse` interface.  Most typically, this will
be an instance of the :class:`pyramid.response.Response` class or a subclass.
If a civilian returns a non-Response object from a view callable that isn't
configured to use a :term:`renderer`, he will typically expect the router to
Pyramid, in various places, adapts the result of calling a view callable to the
:class:`~pyramid.interfaces.IResponse` interface to ensure that the object
returned by the view callable is a "true" response object.  The vast majority
of time, the result of this adaptation is the result object itself, as view
callables written by "civilians" who read the narrative documentation contained
in this manual will always return something that implements the
:class:`~pyramid.interfaces.IResponse` interface.  Most typically, this will be
an instance of the :class:`pyramid.response.Response` class or a subclass. If a
civilian returns a non-Response object from a view callable that isn't
configured to use a :term:`renderer`, they will typically expect the router to
raise an error.  However, you can hook Pyramid in such a way that users can
return arbitrary values from a view callable by providing an adapter which
converts the arbitrary return value into something that implements
:class:`~pyramid.interfaces.IResponse`.
For example, if you'd like to allow view callables to return bare string
objects (without requiring a :term:`renderer` to convert a string to a
response object), you can register an adapter which converts the string to a
Response:
objects (without requiring a :term:`renderer` to convert a string to a response
object), you can register an adapter which converts the string to a Response:
.. code-block:: python
   :linenos:
@@ -754,9 +748,9 @@
   config.add_response_adapter(string_response_adapter, str)
Likewise, if you want to be able to return a simplified kind of response
object from view callables, you can use the IResponse hook to register an
adapter to the more complex IResponse interface:
Likewise, if you want to be able to return a simplified kind of response object
from view callables, you can use the IResponse hook to register an adapter to
the more complex IResponse interface:
.. code-block:: python
   :linenos:
@@ -777,7 +771,7 @@
If you want to implement your own Response object instead of using the
:class:`pyramid.response.Response` object in any capacity at all, you'll have
to make sure the object implements every attribute and method outlined in
to make sure that the object implements every attribute and method outlined in
:class:`pyramid.interfaces.IResponse` and you'll have to ensure that it uses
``zope.interface.implementer(IResponse)`` as a class decorator.
@@ -789,7 +783,7 @@
   @implementer(IResponse)
   class MyResponse(object):
       # ... an implementation of every method and attribute
       # ... an implementation of every method and attribute
       # documented in IResponse should follow ...
When an alternate response object implementation is returned by a view
@@ -804,8 +798,8 @@
subclasses of the class) will natively provide IResponse.  The adapter
registered for ``webob.Response`` simply returns the response object.
Instead of using :meth:`pyramid.config.Configurator.add_response_adapter`,
you can use the :class:`pyramid.response.response_adapter` decorator:
Instead of using :meth:`pyramid.config.Configurator.add_response_adapter`, you
can use the :class:`pyramid.response.response_adapter` decorator:
.. code-block:: python
   :linenos:
@@ -841,31 +835,29 @@
A view mapper is an object that accepts a set of keyword arguments and which
returns a callable.  The returned callable is called with the :term:`view
callable` object.  The returned callable should itself return another
callable which can be called with the "internal calling protocol" ``(context,
callable` object.  The returned callable should itself return another callable
which can be called with the "internal calling protocol" ``(context,
request)``.
You can use a view mapper in a number of ways:
- by setting a ``__view_mapper__`` attribute (which is the view mapper
  object) on the view callable itself
- by setting a ``__view_mapper__`` attribute (which is the view mapper object)
  on the view callable itself
- by passing the mapper object to
  :meth:`pyramid.config.Configurator.add_view` (or its declarative/decorator
  equivalents) as the ``mapper`` argument.
- by passing the mapper object to :meth:`pyramid.config.Configurator.add_view`
  (or its declarative and decorator equivalents) as the ``mapper`` argument
- by registering a *default* view mapper.
- by registering a *default* view mapper
Here's an example of a view mapper that emulates (somewhat) a Pylons
"controller".  The mapper is initialized with some keyword arguments.  Its
``__call__`` method accepts the view object (which will be a class).  It uses
the ``attr`` keyword argument it is passed to determine which attribute
should be used as an action method.  The wrapper method it returns accepts
``(context, request)`` and returns the result of calling the action method
with keyword arguments implied by the :term:`matchdict` after popping the
``action`` out of it.  This somewhat emulates the Pylons style of calling
action methods with routing parameters pulled out of the route matching dict
as keyword arguments.
the ``attr`` keyword argument it is passed to determine which attribute should
be used as an action method.  The wrapper method it returns accepts ``(context,
request)`` and returns the result of calling the action method with keyword
arguments implied by the :term:`matchdict` after popping the ``action`` out of
it.  This somewhat emulates the Pylons style of calling action methods with
routing parameters pulled out of the route matching dict as keyword arguments.
.. code-block:: python
   :linenos:
@@ -917,8 +909,8 @@
set a *default* view mapper (overriding the superdefault view mapper used by
Pyramid itself).
A *single* view registration can use a view mapper by passing the mapper as
the ``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.
A *single* view registration can use a view mapper by passing the mapper as the
``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.
.. index::
   single: configuration decorator
@@ -928,14 +920,14 @@
Registering Configuration Decorators
------------------------------------
Decorators such as :class:`~pyramid.view.view_config` don't change the
behavior of the functions or classes they're decorating.  Instead, when a
:term:`scan` is performed, a modified version of the function or class is
registered with :app:`Pyramid`.
Decorators such as :class:`~pyramid.view.view_config` don't change the behavior
of the functions or classes they're decorating.  Instead when a :term:`scan` is
performed, a modified version of the function or class is registered with
:app:`Pyramid`.
You may wish to have your own decorators that offer such behaviour. This is
possible by using the :term:`Venusian` package in the same way that it is
used by :app:`Pyramid`.
possible by using the :term:`Venusian` package in the same way that it is used
by :app:`Pyramid`.
By way of example, let's suppose you want to write a decorator that registers
the function it wraps with a :term:`Zope Component Architecture` "utility"
@@ -945,8 +937,7 @@
completed. A normal decorator would fail as it would be executed before the
configuration had even begun.
However, using :term:`Venusian`, the decorator could be written as
follows:
However, using :term:`Venusian`, the decorator could be written as follows:
.. code-block:: python
   :linenos:
@@ -968,18 +959,17 @@
           venusian.attach(wrapped, self.register)
           return wrapped
This decorator could then be used to register functions throughout
your code:
This decorator could then be used to register functions throughout your code:
.. code-block:: python
   :linenos:
   @registerFunction('/some/path')
   def my_function():
      do_stuff()
       do_stuff()
However, the utility would only be looked up when a :term:`scan` was
performed, enabling you to set up the utility in advance:
However, the utility would only be looked up when a :term:`scan` was performed,
enabling you to set up the utility in advance:
.. code-block:: python
   :linenos:
@@ -994,10 +984,10 @@
   class UtilityImplementation:
       def __init__(self):
          self.registrations = {}
           self.registrations = {}
       def register(self, path, callable_):
          self.registrations[path] = callable_
           self.registrations[path] = callable_
   if __name__ == '__main__':
       config = Configurator()
@@ -1021,27 +1011,27 @@
A :term:`tween` (a contraction of the word "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
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` :term:`middleware` but they have the benefit of
behave a bit like :term:`WSGI` :term:`middleware`, but they have the benefit of
running in a context in which they have access to the Pyramid :term:`request`,
:term:`response` and :term:`application registry` as well as the Pyramid
:term:`response`, and :term:`application registry`, as well as the Pyramid
rendering machinery.
Creating a Tween
~~~~~~~~~~~~~~~~
To create a tween, you must write a "tween factory".  A tween factory
must be a globally importable callable which accepts two arguments:
``handler`` and ``registry``.  ``handler`` will be either the main
Pyramid request handling function or another tween.  ``registry`` will be the
Pyramid :term:`application registry` represented by this Configurator.  A
tween factory must return the tween (a callable object) when it is called.
To create a tween, you must write a "tween factory".  A tween factory must be a
globally importable callable which accepts two arguments: ``handler`` and
``registry``.  ``handler`` will be either the main Pyramid request handling
function or another tween.  ``registry`` will be the Pyramid :term:`application
registry` represented by this Configurator.  A tween factory must return the
tween (a callable object) when it is called.
A tween is called with a single argument, ``request``, which is the
:term:`request` created by Pyramid's router when it receives a WSGI request.
A tween should return a :term:`response`, usually the one generated by the
:term:`request` created by Pyramid's router when it receives a WSGI request. A
tween should return a :term:`response`, usually the one generated by the
downstream Pyramid application.
You can write the tween factory as a simple closure-returning function:
@@ -1089,14 +1079,14 @@
            return response
You should avoid mutating any state on the tween instance. The tween is
invoked once per request and any shared mutable state needs to be carefully
handled to avoid any race conditions.
You should avoid mutating any state on the tween instance. The tween is invoked
once per request and any shared mutable state needs to be carefully handled to
avoid any race conditions.
The closure style performs slightly better and enables you to conditionally
omit the tween from the request processing pipeline (see the following timing
tween example), whereas the class style makes it easier to have shared mutable
state, and it allows subclassing.
state and allows subclassing.
Here's a complete example of a tween that logs the time spent processing each
request:
@@ -1131,13 +1121,12 @@
In the above example, the tween factory defines a ``timing_tween`` tween and
returns it if ``asbool(registry.settings.get('do_timing'))`` is true.  It
otherwise simply returns the handler it was given.  The ``registry.settings``
attribute is a handle to the deployment settings provided by the user
(usually in an ``.ini`` file).  In this case, if the user has defined a
``do_timing`` setting, and that setting is ``True``, the user has said she
wants to do timing, so the tween factory returns the timing tween; it
otherwise just returns the handler it has been provided, preventing any
timing.
otherwise simply returns the handler which it was given.  The
``registry.settings`` attribute is a handle to the deployment settings provided
by the user (usually in an ``.ini`` file).  In this case, if the user has
defined a ``do_timing`` setting and that setting is ``True``, the user has said
they want to do timing, so the tween factory returns the timing tween; it
otherwise just returns the handler it has been provided, preventing any timing.
The example timing tween simply records the start time, calls the downstream
handler, logs the number of seconds consumed by the downstream handler, and
@@ -1163,29 +1152,28 @@
Note that you must use a :term:`dotted Python name` as the first argument to
:meth:`pyramid.config.Configurator.add_tween`; this must point at a tween
factory.  You cannot pass the tween factory object itself to the method: it
must be :term:`dotted Python name` that points to a globally importable
object.  In the above example, we assume that a ``timing_tween_factory``
tween factory was defined in a module named ``myapp.tweens``, so the tween
factory is importable as ``myapp.tweens.timing_tween_factory``.
must be :term:`dotted Python name` that points to a globally importable object.
In the above example, we assume that a ``timing_tween_factory`` tween factory
was defined in a module named ``myapp.tweens``, so the tween factory is
importable as ``myapp.tweens.timing_tween_factory``.
When you use :meth:`pyramid.config.Configurator.add_tween`, you're
instructing the system to use your tween factory at startup time unless the
user has provided an explicit tween list in his configuration.  This is
what's meant by an "implicit" tween.  A user can always elect to supply an
explicit tween list, reordering or disincluding implicitly added tweens.  See
When you use :meth:`pyramid.config.Configurator.add_tween`, you're instructing
the system to use your tween factory at startup time unless the user has
provided an explicit tween list in their configuration.  This is what's meant
by an "implicit" tween.  A user can always elect to supply an explicit tween
list, reordering or disincluding implicitly added tweens.  See
:ref:`explicit_tween_ordering` for more information about explicit tween
ordering.
If more than one call to :meth:`pyramid.config.Configurator.add_tween` is
made within a single application configuration, the tweens will be chained
together at application startup time.  The *first* tween factory added via
``add_tween`` will be called with the Pyramid exception view tween factory as
its ``handler`` argument, then the tween factory added directly after that
one will be called with the result of the first tween factory as its
``handler`` argument, and so on, ad infinitum until all tween factories have
been called. 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.  For example:
If more than one call to :meth:`pyramid.config.Configurator.add_tween` is made
within a single application configuration, the tweens will be chained together
at application startup time.  The *first* tween factory added via ``add_tween``
will be called with the Pyramid exception view tween factory as its ``handler``
argument, then the tween factory added directly after that one will be called
with the result of the first tween factory as its ``handler`` argument, and so
on, ad infinitum until all tween factories have been called. 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.  For example:
.. code-block:: python
    :linenos:
@@ -1196,8 +1184,7 @@
    config.add_tween('myapp.tween_factory1')
    config.add_tween('myapp.tween_factory2')
The above example will generate an implicit tween chain that looks like
this::
The above example will generate an implicit tween chain that looks like this::
    INGRESS (implicit)
    myapp.tween_factory2
@@ -1211,37 +1198,36 @@
By default, as described above, the ordering of the chain is controlled
entirely by the relative ordering of calls to
:meth:`pyramid.config.Configurator.add_tween`.  However, the caller of
add_tween can provide an optional hint that can influence the implicit tween
chain ordering by supplying ``under`` or ``over`` (or both) arguments to
:meth:`~pyramid.config.Configurator.add_tween`.  These hints are only
used when an explicit tween ordering is not used. See
:ref:`explicit_tween_ordering` for a description of how to set an explicit
tween ordering.
``add_tween`` can provide an optional hint that can influence the implicit
tween chain ordering by supplying ``under`` or ``over`` (or both) arguments to
:meth:`~pyramid.config.Configurator.add_tween`.  These hints are only used when
an explicit tween ordering is not used. See :ref:`explicit_tween_ordering` for
a description of how to set an explicit tween ordering.
Allowable values for ``under`` or ``over`` (or both) are:
- ``None`` (the default).
- ``None`` (the default),
- A :term:`dotted Python name` to a tween factory: a string representing the
  predicted dotted name of a tween factory added in a call to ``add_tween``
  in the same configuration session.
- a :term:`dotted Python name` to a tween factory: a string representing the
  predicted dotted name of a tween factory added in a call to ``add_tween`` in
  the same configuration session,
- One of the constants :attr:`pyramid.tweens.MAIN`,
  :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`.
- one of the constants :attr:`pyramid.tweens.MAIN`,
  :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`, or
- An iterable of any combination of the above. This allows the user to specify
- an iterable of any combination of the above. This allows the user to specify
  fallbacks if the desired tween is not included, as well as compatibility
  with multiple other tweens.
Effectively, ``over`` means "closer to the request ingress than" and
``under`` means "closer to the main Pyramid application than".
You can think of an onion with outer layers over the inner layers,
the application being under all the layers at the center.
Effectively, ``over`` means "closer to the request ingress than" and ``under``
means "closer to the main Pyramid application than". You can think of an onion
with outer layers over the inner layers, the application being under all the
layers at the center.
For example, the following call to
:meth:`~pyramid.config.Configurator.add_tween` will attempt to place the
tween factory represented by ``myapp.tween_factory`` directly 'above' (in
``ptweens`` order) the main Pyramid request handler.
:meth:`~pyramid.config.Configurator.add_tween` will attempt to place the tween
factory represented by ``myapp.tween_factory`` directly "above" (in ``ptweens``
order) the main Pyramid request handler.
.. code-block:: python
   :linenos:
@@ -1250,8 +1236,7 @@
   config.add_tween('myapp.tween_factory', over=pyramid.tweens.MAIN)
The above example will generate an implicit tween chain that looks like
this::
The above example will generate an implicit tween chain that looks like this::
    INGRESS (implicit)
    pyramid.tweens.excview_tween_factory (implicit)
@@ -1259,9 +1244,8 @@
    MAIN (implicit)
Likewise, calling the following call to
:meth:`~pyramid.config.Configurator.add_tween` will attempt to place this
tween factory 'above' the main handler but 'below' a separately added tween
factory:
:meth:`~pyramid.config.Configurator.add_tween` will attempt to place this tween
factory "above" the main handler but "below" a separately added tween factory:
.. code-block:: python
   :linenos:
@@ -1274,8 +1258,7 @@
                    over=pyramid.tweens.MAIN,
                    under='myapp.tween_factory1')
The above example will generate an implicit tween chain that looks like
this::
The above example will generate an implicit tween chain that looks like this::
    INGRESS (implicit)
    pyramid.tweens.excview_tween_factory (implicit)
@@ -1288,28 +1271,28 @@
If all options for ``under`` (or ``over``) cannot be found in the current
configuration, it is an error. If some options are specified purely for
compatibilty with other tweens, just add a fallback of MAIN or INGRESS.
For example, ``under=('someothertween', 'someothertween2', INGRESS)``.
This constraint will require the tween to be located under both the
'someothertween' tween, the 'someothertween2' tween, and INGRESS. If any of
these is not in the current configuration, this constraint will only organize
itself based on the tweens that are present.
compatibilty with other tweens, just add a fallback of ``MAIN`` or ``INGRESS``.
For example, ``under=('someothertween', 'someothertween2', INGRESS)``. This
constraint will require the tween to be located under the ``someothertween``
tween, the ``someothertween2`` tween, and ``INGRESS``. If any of these is not
in the current configuration, this constraint will only organize itself based
on the tweens that are present.
.. _explicit_tween_ordering:
Explicit Tween Ordering
~~~~~~~~~~~~~~~~~~~~~~~
Implicit tween ordering is obviously only best-effort.  Pyramid will attempt
to provide an implicit order of tweens as best it can using hints provided by
calls to :meth:`~pyramid.config.Configurator.add_tween`, but because it's
only best-effort, if very precise tween ordering is required, the only
surefire way to get it is to use an explicit tween order.  The deploying user
can override the implicit tween inclusion and ordering implied by calls to
Implicit tween ordering is obviously only best-effort.  Pyramid will attempt to
provide an implicit order of tweens as best it can using hints provided by
calls to :meth:`~pyramid.config.Configurator.add_tween`.  But because it's only
best-effort, if very precise tween ordering is required, the only surefire way
to get it is to use an explicit tween order.  The deploying user can override
the implicit tween inclusion and ordering implied by calls to
:meth:`~pyramid.config.Configurator.add_tween` entirely by using the
``pyramid.tweens`` settings value.  When used, this settings value must be a
list of Python dotted names which will override the ordering (and inclusion)
of tween factories in the implicit tween chain.  For example:
list of Python dotted names which will override the ordering (and inclusion) of
tween factories in the implicit tween chain.  For example:
.. code-block:: ini
   :linenos:
@@ -1327,19 +1310,19 @@
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:`dotted Python
name` which points to a tween factory) instead of any tween factories added
via :meth:`pyramid.config.Configurator.add_tween`.  The *first* tween factory
in the ``pyramid.tweens`` list will be used as the producer of the effective
``pyramid.tweens`` configuration setting (each is a :term:`dotted Python name`
which points to a tween factory) instead of any tween factories added via
:meth:`pyramid.config.Configurator.add_tween`.  The *first* 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 "below" it, ad infinitum.  The "main" Pyramid request
handler is implicit, and always "at the bottom".
declared directly "below" it, ad infinitum.  The "main" Pyramid request handler
is implicit, and always "at the bottom".
.. 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
   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
@@ -1348,30 +1331,30 @@
Tween Conflicts and Ordering Cycles
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pyramid will prevent the same tween factory from being added to the 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 a separate globally importable
instance object from the factory that it conflicts with 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
Pyramid will prevent the same tween factory from being added to the 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 a separate globally importable instance object from
the factory that it conflicts with; (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`.
If a cycle is detected in implicit tween ordering when ``over`` and ``under``
are used in any call to "add_tween", an exception will be raised at startup
are used in any call to ``add_tween``, an exception will be raised at startup
time.
Displaying Tween Ordering
~~~~~~~~~~~~~~~~~~~~~~~~~
The ``ptweens`` command-line utility can be used to report the current
implict and explicit tween chains used by an application.  See
The ``ptweens`` command-line utility can be used to report the current implict
and explicit tween chains used by an application.  See
:ref:`displaying_tweens`.
.. _registering_thirdparty_predicates:
Adding A Third Party View, Route, or Subscriber Predicate
Adding a Third Party View, Route, or Subscriber Predicate
---------------------------------------------------------
.. versionadded:: 1.4
@@ -1381,10 +1364,10 @@
View and Route Predicates
~~~~~~~~~~~~~~~~~~~~~~~~~
View and route predicates used during configuration allow you to narrow the
set of circumstances under which a view or route will match.  For example,
the ``request_method`` view predicate can be used to ensure a view callable
is only invoked when the request's method is ``POST``:
View and route predicates used during configuration allow you to narrow the set
of circumstances under which a view or route will match.  For example, the
``request_method`` view predicate can be used to ensure a view callable is only
invoked when the request's method is ``POST``:
.. code-block:: python
@@ -1398,9 +1381,9 @@
    config.add_route('name', '/foo', request_method='POST')
Many other built-in predicates exists (``request_param``, and others).  You
can add third-party predicates to the list of available predicates by using
one of :meth:`pyramid.config.Configurator.add_view_predicate` or
Many other built-in predicates exists (``request_param``, and others).  You can
add third-party predicates to the list of available predicates by using one of
:meth:`pyramid.config.Configurator.add_view_predicate` or
:meth:`pyramid.config.Configurator.add_route_predicate`.  The former adds a
view predicate, the latter a route predicate.
@@ -1428,7 +1411,7 @@
The second argument is a view or route predicate factory, or a :term:`dotted
Python name` which refers to a view or route predicate factory.  A view or
route predicate factory is most often a class with a constructor
(``__init__``), a ``text`` method, a ``phash`` method and a ``__call__``
(``__init__``), a ``text`` method, a ``phash`` method, and a ``__call__``
method. For example:
.. code-block:: python
@@ -1448,27 +1431,27 @@
The constructor of a predicate factory takes two arguments: ``val`` and
``config``.  The ``val`` argument will be the argument passed to
``view_config`` (or ``add_view``).  In the example above, it will be the
string ``File``.  The second arg, ``config`` will be the Configurator
instance at the time of configuration.
``view_config`` (or ``add_view``).  In the example above, it will be the string
``File``.  The second argument, ``config``, will be the Configurator instance
at the time of configuration.
The ``text`` method must return a string.  It should be useful to describe
the behavior of the predicate in error messages.
The ``text`` method must return a string.  It should be useful to describe the
behavior of the predicate in error messages.
The ``phash`` method must return a string or a sequence of strings.  It's
most often the same as ``text``, as long as ``text`` uniquely describes the
predicate's name and the value passed to the constructor.  If ``text`` is
more general, or doesn't describe things that way, ``phash`` should return a
string with the name and the value serialized.  The result of ``phash`` is
not seen in output anywhere, it just informs the uniqueness constraints for
view configuration.
The ``phash`` method must return a string or a sequence of strings.  It's most
often the same as ``text``, as long as ``text`` uniquely describes the
predicate's name and the value passed to the constructor.  If ``text`` is more
general, or doesn't describe things that way, ``phash`` should return a string
with the name and the value serialized.  The result of ``phash`` is not seen in
output anywhere, it just informs the uniqueness constraints for view
configuration.
The ``__call__`` method of a predicate factory must accept a resource
(``context``) and a request, and must return ``True`` or ``False``.  It is
the "meat" of the predicate.
(``context``) and a request, and must return ``True`` or ``False``.  It is the
"meat" of the predicate.
You can use the same predicate factory as both a view predicate and as a
route predicate, but you'll need to call ``add_view_predicate`` and
You can use the same predicate factory as both a view predicate and as a route
predicate, but you'll need to call ``add_view_predicate`` and
``add_route_predicate`` separately with the same factory.
.. _subscriber_predicates:
@@ -1476,16 +1459,16 @@
Subscriber Predicates
~~~~~~~~~~~~~~~~~~~~~
Subscriber predicates work almost exactly like view and route predicates.
They narrow the set of circumstances in which a subscriber will be called.
There are several minor differences between a subscriber predicate and a
view/route predicate:
Subscriber predicates work almost exactly like view and route predicates. They
narrow the set of circumstances in which a subscriber will be called. There are
several minor differences between a subscriber predicate and a view or route
predicate:
- There are no default subscriber predicates.  You must register one to use
  one.
- The ``__call__`` method of a subscriber predicate accepts a single
  ``event`` object instead of a ``context`` and a ``request``.
- The ``__call__`` method of a subscriber predicate accepts a single ``event``
  object instead of a ``context`` and a ``request``.
- Not every subscriber predicate can be used with every event type.  Some
  subscriber predicates will assume a certain event type.
@@ -1519,8 +1502,8 @@
Once a subscriber predicate is registered, you can use it in a call to
:meth:`pyramid.config.Configurator.add_subscriber` or to
:class:`pyramid.events.subscriber`.  Here's an example of using the
previously registered ``request_path_startswith`` predicate in a call to
:class:`pyramid.events.subscriber`.  Here's an example of using the previously
registered ``request_path_startswith`` predicate in a call to
:meth:`~pyramid.config.Configurator.add_subscriber`:
.. code-block:: python
@@ -1533,7 +1516,7 @@
    # and at configuration time
    config.add_subscriber(yosubscriber, NewRequest,
    config.add_subscriber(yosubscriber, NewRequest,
           request_path_startswith='/add_yo')
Here's the same subscriber/predicate/event-type combination used via
@@ -1548,22 +1531,19 @@
    def yosubscriber(event):
        event.request.yo = 'YO!'
In either of the above configurations, the ``yosubscriber`` callable will
only be called if the request path starts with ``/add_yo``.  Otherwise the
event subscriber will not be called.
In either of the above configurations, the ``yosubscriber`` callable will only
be called if the request path starts with ``/add_yo``.  Otherwise the event
subscriber will not be called.
Note that the ``request_path_startswith`` subscriber you defined can be used
with events that have a ``request`` attribute, but not ones that do not.  So,
for example, the predicate can be used with subscribers registered for
:class:`pyramid.events.NewRequest` and :class:`pyramid.events.ContextFound`
events, but it cannot be used with subscribers registered for
:class:`pyramid.events.ApplicationCreated` because the latter type of event
has no ``request`` attribute.  The point being: unlike route and view
predicates, not every type of subscriber predicate will necessarily be
applicable for use in every subscriber registration.  It is not the
responsibility of the predicate author to make every predicate make sense for
every event type; it is the responsibility of the predicate consumer to use
predicates that make sense for a particular event type registration.
:class:`pyramid.events.ApplicationCreated` because the latter type of event has
no ``request`` attribute.  The point being, unlike route and view predicates,
not every type of subscriber predicate will necessarily be applicable for use
in every subscriber registration.  It is not the responsibility of the
predicate author to make every predicate make sense for every event type; it is
the responsibility of the predicate consumer to use predicates that make sense
for a particular event type registration.