summaryrefslogtreecommitdiff
path: root/docs/narr/events.rst
diff options
context:
space:
mode:
authorChristoph Zwerschke <cito@online.de>2016-04-19 20:07:12 +0200
committerChristoph Zwerschke <cito@online.de>2016-04-19 20:07:12 +0200
commit3629c49e46207ff5162a82883c14937e6ef4c186 (patch)
tree1306181202cb8313f16080789f5b9ab1eeb61d53 /docs/narr/events.rst
parent804ba0b2f434781e77d2b5191f1cd76a490f6610 (diff)
parent6c16fb020027fac47e4d2e335cd9e264dba8aa3b (diff)
downloadpyramid-3629c49e46207ff5162a82883c14937e6ef4c186.tar.gz
pyramid-3629c49e46207ff5162a82883c14937e6ef4c186.tar.bz2
pyramid-3629c49e46207ff5162a82883c14937e6ef4c186.zip
Merge remote-tracking branch 'refs/remotes/Pylons/master'
Diffstat (limited to 'docs/narr/events.rst')
-rw-r--r--docs/narr/events.rst193
1 files changed, 135 insertions, 58 deletions
diff --git a/docs/narr/events.rst b/docs/narr/events.rst
index 929208083..c10d4cc47 100644
--- a/docs/narr/events.rst
+++ b/docs/narr/events.rst
@@ -9,42 +9,39 @@
.. _events_chapter:
Using Events
-=============
+============
-An *event* is an object broadcast by the :app:`Pyramid` framework
-at interesting points during the lifetime of an application. You
-don't need to use events in order to create most :app:`Pyramid`
-applications, but they can be useful when you want to perform slightly
-advanced operations. For example, subscribing to an event can allow
-you to run some code as the result of every new request.
+An *event* is an object broadcast by the :app:`Pyramid` framework at
+interesting points during the lifetime of an application. You don't need to
+use events in order to create most :app:`Pyramid` applications, but they can be
+useful when you want to perform slightly advanced operations. For example,
+subscribing to an event can allow you to run some code as the result of every
+new request.
-Events in :app:`Pyramid` are always broadcast by the framework.
-However, they only become useful when you register a *subscriber*. A
-subscriber is a function that accepts a single argument named `event`:
+Events in :app:`Pyramid` are always broadcast by the framework. However, they
+only become useful when you register a *subscriber*. A subscriber is a
+function that accepts a single argument named `event`:
.. code-block:: python
:linenos:
def mysubscriber(event):
- print event
+ print(event)
-The above is a subscriber that simply prints the event to the console
-when it's called.
+The above is a subscriber that simply prints the event to the console when it's
+called.
The mere existence of a subscriber function, however, is not sufficient to
arrange for it to be called. To arrange for the subscriber to be called,
-you'll need to use the
-:meth:`pyramid.config.Configurator.add_subscriber` method or you'll
-need to use the :func:`pyramid.events.subscriber` decorator to decorate a
-function found via a :term:`scan`.
+you'll need to use the :meth:`pyramid.config.Configurator.add_subscriber`
+method or you'll need to use the :func:`pyramid.events.subscriber` decorator to
+decorate a function found via a :term:`scan`.
Configuring an Event Listener Imperatively
------------------------------------------
-You can imperatively configure a subscriber function to be called
-for some event type via the
-:meth:`~pyramid.config.Configurator.add_subscriber`
-method (see also :term:`Configurator`):
+You can imperatively configure a subscriber function to be called for some
+event type via the :meth:`~pyramid.config.Configurator.add_subscriber` method:
.. code-block:: python
:linenos:
@@ -53,21 +50,24 @@ method (see also :term:`Configurator`):
from subscribers import mysubscriber
- # "config" below is assumed to be an instance of a
+ # "config" below is assumed to be an instance of a
# pyramid.config.Configurator object
config.add_subscriber(mysubscriber, NewRequest)
-The first argument to
-:meth:`~pyramid.config.Configurator.add_subscriber` is the
-subscriber function (or a :term:`dotted Python name` which refers
-to a subscriber callable); the second argument is the event type.
+The first argument to :meth:`~pyramid.config.Configurator.add_subscriber` is
+the subscriber function (or a :term:`dotted Python name` which refers to a
+subscriber callable); the second argument is the event type.
+
+.. seealso::
+
+ See also :term:`Configurator`.
Configuring an Event Listener Using a Decorator
-----------------------------------------------
-You can configure a subscriber function to be called for some event
-type via the :func:`pyramid.events.subscriber` function.
+You can configure a subscriber function to be called for some event type via
+the :func:`pyramid.events.subscriber` function.
.. code-block:: python
:linenos:
@@ -77,11 +77,11 @@ type via the :func:`pyramid.events.subscriber` function.
@subscriber(NewRequest)
def mysubscriber(event):
- event.request.foo = 1
+ event.request.foo = 1
-When the :func:`~pyramid.events.subscriber` decorator is used a
-:term:`scan` must be performed against the package containing the
-decorated function for the decorator to have any effect.
+When the :func:`~pyramid.events.subscriber` decorator is used, a :term:`scan`
+must be performed against the package containing the decorated function for the
+decorator to have any effect.
Either of the above registration examples implies that every time the
:app:`Pyramid` framework emits an event object that supplies an
@@ -92,13 +92,12 @@ As you can see, a subscription is made in terms of a *class* (such as
:class:`pyramid.events.NewResponse`). The event object sent to a subscriber
will always be an object that possesses an :term:`interface`. For
:class:`pyramid.events.NewResponse`, that interface is
-:class:`pyramid.interfaces.INewResponse`. The interface documentation
-provides information about available attributes and methods of the event
-objects.
+:class:`pyramid.interfaces.INewResponse`. The interface documentation provides
+information about available attributes and methods of the event objects.
-The return value of a subscriber function is ignored. Subscribers to
-the same event type are not guaranteed to be called in any particular
-order relative to each other.
+The return value of a subscriber function is ignored. Subscribers to the same
+event type are not guaranteed to be called in any particular order relative to
+each other.
All the concrete :app:`Pyramid` event types are documented in the
:ref:`events_module` API documentation.
@@ -106,21 +105,20 @@ All the concrete :app:`Pyramid` event types are documented in the
An Example
----------
-If you create event listener functions in a ``subscribers.py`` file in
-your application like so:
+If you create event listener functions in a ``subscribers.py`` file in your
+application like so:
.. code-block:: python
:linenos:
def handle_new_request(event):
- print 'request', event.request
+ print('request', event.request)
def handle_new_response(event):
- print 'response', event.response
+ print('response', event.response)
-You may configure these functions to be called at the appropriate
-times by adding the following code to your application's
-configuration startup:
+You may configure these functions to be called at the appropriate times by
+adding the following code to your application's configuration startup:
.. code-block:: python
:linenos:
@@ -132,21 +130,100 @@ configuration startup:
config.add_subscriber('myproject.subscribers.handle_new_response',
'pyramid.events.NewResponse')
-Either mechanism causes the functions in ``subscribers.py`` to be
-registered as event subscribers. Under this configuration, when the
-application is run, each time a new request or response is detected, a
-message will be printed to the console.
+Either mechanism causes the functions in ``subscribers.py`` to be registered as
+event subscribers. Under this configuration, when the application is run, each
+time a new request or response is detected, a message will be printed to the
+console.
-Each of our subscriber functions accepts an ``event`` object and
-prints an attribute of the event object. This begs the question: how
-can we know which attributes a particular event has?
+Each of our subscriber functions accepts an ``event`` object and prints an
+attribute of the event object. This begs the question: how can we know which
+attributes a particular event has?
We know that :class:`pyramid.events.NewRequest` event objects have a
-``request`` attribute, which is a :term:`request` object, because the
-interface defined at :class:`pyramid.interfaces.INewRequest` says it must.
-Likewise, we know that :class:`pyramid.interfaces.NewResponse` events have a
-``response`` attribute, which is a response object constructed by your
-application, because the interface defined at
-:class:`pyramid.interfaces.INewResponse` says it must
+``request`` attribute, which is a :term:`request` object, because the interface
+defined at :class:`pyramid.interfaces.INewRequest` says it must. Likewise, we
+know that :class:`pyramid.interfaces.NewResponse` events have a ``response``
+attribute, which is a response object constructed by your application, because
+the interface defined at :class:`pyramid.interfaces.INewResponse` says it must
(:class:`pyramid.events.NewResponse` objects also have a ``request``).
+.. _custom_events:
+
+Creating Your Own Events
+------------------------
+
+In addition to using the events that the Pyramid framework creates, you can
+create your own events for use in your application. This can be useful to
+decouple parts of your application.
+
+For example, suppose your application has to do many things when a new document
+is created. Rather than putting all this logic in the view that creates the
+document, you can create the document in your view and then fire a custom
+event. Subscribers to the custom event can take other actions, such as indexing
+the document, sending email, or sending a message to a remote system.
+
+An event is simply an object. There are no required attributes or method for
+your custom events. In general, your events should keep track of the
+information that subscribers will need. Here are some example custom event
+classes:
+
+.. code-block:: python
+ :linenos:
+
+ class DocCreated(object):
+ def __init__(self, doc, request):
+ self.doc = doc
+ self.request = request
+
+ class UserEvent(object):
+ def __init__(self, user):
+ self.user = user
+
+ class UserLoggedIn(UserEvent):
+ pass
+
+Some Pyramid applications choose to define custom events classes in an
+``events`` module.
+
+You can subscribe to custom events in the same way that you subscribe to
+Pyramid events—either imperatively or with a decorator. You can also use custom
+events with :ref:`subscriber predicates <subscriber_predicates>`. Here's an
+example of subscribing to a custom event with a decorator:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.events import subscriber
+ from .events import DocCreated
+ from .index import index_doc
+
+ @subscriber(DocCreated)
+ def index_doc(event):
+ # index the document using our application's index_doc function
+ index_doc(event.doc, event.request)
+
+The above example assumes that the application defines a ``DocCreated`` event
+class and an ``index_doc`` function.
+
+To fire your custom events use the :meth:`pyramid.registry.Registry.notify`
+method, which is most often accessed as ``request.registry.notify``. For
+example:
+
+.. code-block:: python
+ :linenos:
+
+ from .events import DocCreated
+
+ def new_doc_view(request):
+ doc = MyDoc()
+ event = DocCreated(doc, request)
+ request.registry.notify(event)
+ return {'document': doc}
+
+This example view will notify all subscribers to the custom ``DocCreated``
+event.
+
+Note that when you fire an event, all subscribers are run synchronously so it's
+generally not a good idea to create event handlers that may take a long time to
+run. Although event handlers could be used as a central place to spawn tasks on
+your own message queues.