Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/pyramid/events.py : 61%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import venusian
3from zope.interface import implementer, Interface
5from pyramid.interfaces import (
6 IContextFound,
7 INewRequest,
8 INewResponse,
9 IApplicationCreated,
10 IBeforeRender,
11 IBeforeTraversal,
12)
15class subscriber(object):
16 """ Decorator activated via a :term:`scan` which treats the function
17 being decorated as an event subscriber for the set of interfaces passed
18 as ``*ifaces`` and the set of predicate terms passed as ``**predicates``
19 to the decorator constructor.
21 For example:
23 .. code-block:: python
25 from pyramid.events import NewRequest
26 from pyramid.events import subscriber
28 @subscriber(NewRequest)
29 def mysubscriber(event):
30 event.request.foo = 1
32 More than one event type can be passed as a constructor argument. The
33 decorated subscriber will be called for each event type.
35 .. code-block:: python
37 from pyramid.events import NewRequest, NewResponse
38 from pyramid.events import subscriber
40 @subscriber(NewRequest, NewResponse)
41 def mysubscriber(event):
42 print(event)
44 When the ``subscriber`` decorator is used without passing an arguments,
45 the function it decorates is called for every event sent:
47 .. code-block:: python
49 from pyramid.events import subscriber
51 @subscriber()
52 def mysubscriber(event):
53 print(event)
55 This method will have no effect until a :term:`scan` is performed
56 against the package or module which contains it, ala:
58 .. code-block:: python
60 from pyramid.config import Configurator
61 config = Configurator()
62 config.scan('somepackage_containing_subscribers')
64 Any ``**predicate`` arguments will be passed along to
65 :meth:`pyramid.config.Configurator.add_subscriber`. See
66 :ref:`subscriber_predicates` for a description of how predicates can
67 narrow the set of circumstances in which a subscriber will be called.
69 Two additional keyword arguments which will be passed to the
70 :term:`venusian` ``attach`` function are ``_depth`` and ``_category``.
72 ``_depth`` is provided for people who wish to reuse this class from another
73 decorator. The default value is ``0`` and should be specified relative to
74 the ``subscriber`` invocation. It will be passed in to the
75 :term:`venusian` ``attach`` function as the depth of the callstack when
76 Venusian checks if the decorator is being used in a class or module
77 context. It's not often used, but it can be useful in this circumstance.
79 ``_category`` sets the decorator category name. It can be useful in
80 combination with the ``category`` argument of ``scan`` to control which
81 views should be processed.
83 See the :py:func:`venusian.attach` function in Venusian for more
84 information about the ``_depth`` and ``_category`` arguments.
86 .. versionchanged:: 1.9.1
87 Added the ``_depth`` and ``_category`` arguments.
89 """
91 venusian = venusian # for unit testing
93 def __init__(self, *ifaces, **predicates):
94 self.ifaces = ifaces
95 self.predicates = predicates
96 self.depth = predicates.pop('_depth', 0)
97 self.category = predicates.pop('_category', 'pyramid')
99 def register(self, scanner, name, wrapped):
100 config = scanner.config
101 for iface in self.ifaces or (Interface,):
102 config.add_subscriber(wrapped, iface, **self.predicates)
104 def __call__(self, wrapped):
105 self.venusian.attach(
106 wrapped,
107 self.register,
108 category=self.category,
109 depth=self.depth + 1,
110 )
111 return wrapped
114@implementer(INewRequest)
115class NewRequest(object):
116 """ An instance of this class is emitted as an :term:`event`
117 whenever :app:`Pyramid` begins to process a new request. The
118 event instance has an attribute, ``request``, which is a
119 :term:`request` object. This event class implements the
120 :class:`pyramid.interfaces.INewRequest` interface."""
122 def __init__(self, request):
123 self.request = request
126@implementer(INewResponse)
127class NewResponse(object):
128 """ An instance of this class is emitted as an :term:`event`
129 whenever any :app:`Pyramid` :term:`view` or :term:`exception
130 view` returns a :term:`response`.
132 The instance has two attributes:``request``, which is the request
133 which caused the response, and ``response``, which is the response
134 object returned by a view or renderer.
136 If the ``response`` was generated by an :term:`exception view`, the
137 request will have an attribute named ``exception``, which is the
138 exception object which caused the exception view to be executed. If the
139 response was generated by a 'normal' view, this attribute of the request
140 will be ``None``.
142 This event will not be generated if a response cannot be created due to
143 an exception that is not caught by an exception view (no response is
144 created under this circumstace).
146 This class implements the
147 :class:`pyramid.interfaces.INewResponse` interface.
149 .. note::
151 Postprocessing a response is usually better handled in a WSGI
152 :term:`middleware` component than in subscriber code that is
153 called by a :class:`pyramid.interfaces.INewResponse` event.
154 The :class:`pyramid.interfaces.INewResponse` event exists
155 almost purely for symmetry with the
156 :class:`pyramid.interfaces.INewRequest` event.
157 """
159 def __init__(self, request, response):
160 self.request = request
161 self.response = response
164@implementer(IBeforeTraversal)
165class BeforeTraversal(object):
166 """
167 An instance of this class is emitted as an :term:`event` after the
168 :app:`Pyramid` :term:`router` has attempted to find a :term:`route` object
169 but before any traversal or view code is executed. The instance has an
170 attribute, ``request``, which is the request object generated by
171 :app:`Pyramid`.
173 Notably, the request object **may** have an attribute named
174 ``matched_route``, which is the matched route if found. If no route
175 matched, this attribute is not available.
177 This class implements the :class:`pyramid.interfaces.IBeforeTraversal`
178 interface.
179 """
181 def __init__(self, request):
182 self.request = request
185@implementer(IContextFound)
186class ContextFound(object):
187 """ An instance of this class is emitted as an :term:`event` after
188 the :app:`Pyramid` :term:`router` finds a :term:`context`
189 object (after it performs traversal) but before any view code is
190 executed. The instance has an attribute, ``request``, which is
191 the request object generated by :app:`Pyramid`.
193 Notably, the request object will have an attribute named
194 ``context``, which is the context that will be provided to the
195 view which will eventually be called, as well as other attributes
196 attached by context-finding code.
198 This class implements the
199 :class:`pyramid.interfaces.IContextFound` interface.
201 .. note::
203 As of :app:`Pyramid` 1.0, for backwards compatibility purposes, this
204 event may also be imported as :class:`pyramid.events.AfterTraversal`.
205 """
207 def __init__(self, request):
208 self.request = request
211AfterTraversal = ContextFound # b/c as of 1.0
214@implementer(IApplicationCreated)
215class ApplicationCreated(object):
216 """ An instance of this class is emitted as an :term:`event` when
217 the :meth:`pyramid.config.Configurator.make_wsgi_app` is
218 called. The instance has an attribute, ``app``, which is an
219 instance of the :term:`router` that will handle WSGI requests.
220 This class implements the
221 :class:`pyramid.interfaces.IApplicationCreated` interface.
223 .. note::
225 For backwards compatibility purposes, this class can also be imported as
226 :class:`pyramid.events.WSGIApplicationCreatedEvent`. This was the name
227 of the event class before :app:`Pyramid` 1.0.
228 """
230 def __init__(self, app):
231 self.app = app
232 self.object = app
235WSGIApplicationCreatedEvent = ApplicationCreated # b/c (as of 1.0)
238@implementer(IBeforeRender)
239class BeforeRender(dict):
240 """
241 Subscribers to this event may introspect and modify the set of
242 :term:`renderer globals` before they are passed to a :term:`renderer`.
243 This event object itself has a dictionary-like interface that can be used
244 for this purpose. For example::
246 from pyramid.events import subscriber
247 from pyramid.events import BeforeRender
249 @subscriber(BeforeRender)
250 def add_global(event):
251 event['mykey'] = 'foo'
253 An object of this type is sent as an event just before a :term:`renderer`
254 is invoked.
256 If a subscriber adds a key via ``__setitem__`` that already exists in
257 the renderer globals dictionary, it will overwrite the older value there.
258 This can be problematic because event subscribers to the BeforeRender
259 event do not possess any relative ordering. For maximum interoperability
260 with other third-party subscribers, if you write an event subscriber meant
261 to be used as a BeforeRender subscriber, your subscriber code will need to
262 ensure no value already exists in the renderer globals dictionary before
263 setting an overriding value (which can be done using ``.get`` or
264 ``__contains__`` of the event object).
266 The dictionary returned from the view is accessible through the
267 :attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`
268 event.
270 Suppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from
271 your view callable, like so::
273 from pyramid.view import view_config
275 @view_config(renderer='some_renderer')
276 def myview(request):
277 return {'mykey': 'somevalue', 'mykey2': 'somevalue2'}
279 :attr:`rendering_val` can be used to access these values from the
280 :class:`~pyramid.events.BeforeRender` object::
282 from pyramid.events import subscriber
283 from pyramid.events import BeforeRender
285 @subscriber(BeforeRender)
286 def read_return(event):
287 # {'mykey': 'somevalue'} is returned from the view
288 print(event.rendering_val['mykey'])
290 In other words, :attr:`rendering_val` is the (non-system) value returned
291 by a view or passed to ``render*`` as ``value``. This feature is new in
292 Pyramid 1.2.
294 For a description of the values present in the renderer globals dictionary,
295 see :ref:`renderer_system_values`.
297 .. seealso::
299 See also :class:`pyramid.interfaces.IBeforeRender`.
300 """
302 def __init__(self, system, rendering_val=None):
303 dict.__init__(self, system)
304 self.rendering_val = rendering_val