Steve Piercy
2017-06-27 14c5425d4f031476e38bc4115c2f88b7eb62b21a
commit | author | age
c8cf22 1 .. _hooks_chapter:
CM 2
13c923 3 Using Hooks
CM 4 ===========
c8cf22 5
e1a7e0 6 "Hooks" can be used to influence the behavior of the :app:`Pyramid` framework
CM 7 in various ways.
fab8c5 8
8c56ae 9 .. index::
c5f24b 10    single: not found view
8c56ae 11
7bc20e 12 .. _changing_the_notfound_view:
CM 13
fab8c5 14 Changing the Not Found View
CM 15 ---------------------------
16
8aa1c2 17 When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not Found
SP 18 View`, which is a :term:`view callable`. The default Not Found View can be
19 overridden through application configuration.
ff1213 20
8aa1c2 21 If your application uses :term:`imperative configuration`, you can replace the
SP 22 Not Found View by using the
0db4a1 23 :meth:`pyramid.config.Configurator.add_notfound_view` method:
0ac818 24
e1a7e0 25 .. code-block:: python
CM 26    :linenos:
0ac818 27
439a02 28    def notfound(request):
c898dd 29        return Response('Not Found', status='404 Not Found')
0ac818 30
439a02 31    def main(globals, **settings):
TL 32        config = Configurator()
33        config.add_notfound_view(notfound)
34
35 The :term:`Not Found View` callable is a view callable like any other.
0db4a1 36
CM 37 If your application instead uses :class:`pyramid.view.view_config` decorators
439a02 38 and a :term:`scan`, you can replace the Not Found View by using the
0db4a1 39 :class:`pyramid.view.notfound_view_config` decorator:
CM 40
41 .. code-block:: python
42    :linenos:
43
44    from pyramid.view import notfound_view_config
45
25d7c2 46    @notfound_view_config()
0db4a1 47    def notfound(request):
c898dd 48        return Response('Not Found', status='404 Not Found')
0db4a1 49
CM 50    def main(globals, **settings):
439a02 51        config = Configurator()
TL 52        config.scan()
0db4a1 53
CM 54 This does exactly what the imperative example above showed.
55
2f4bde 56 Your application can define *multiple* Not Found Views if necessary.  Both
0db4a1 57 :meth:`pyramid.config.Configurator.add_notfound_view` and
CM 58 :class:`pyramid.view.notfound_view_config` take most of the same arguments as
59 :class:`pyramid.config.Configurator.add_view` and
2f4bde 60 :class:`pyramid.view.view_config`, respectively.  This means that Not Found
TL 61 Views can carry predicates limiting their applicability.  For example:
0db4a1 62
CM 63 .. code-block:: python
64    :linenos:
65
66    from pyramid.view import notfound_view_config
67
25d7c2 68    @notfound_view_config(request_method='GET')
0db4a1 69    def notfound_get(request):
c898dd 70        return Response('Not Found during GET', status='404 Not Found')
0db4a1 71
25d7c2 72    @notfound_view_config(request_method='POST')
0db4a1 73    def notfound_post(request):
c898dd 74        return Response('Not Found during POST', status='404 Not Found')
0db4a1 75
CM 76    def main(globals, **settings):
77       config = Configurator()
78       config.scan()
79
8aa1c2 80 The ``notfound_get`` view will be called when a view could not be found and the
SP 81 request method was ``GET``.  The ``notfound_post`` view will be called when a
82 view could not be found and the request method was ``POST``.
0ac818 83
cec2b0 84 Like any other view, the Not Found View must accept at least a ``request``
8aa1c2 85 parameter, or both ``context`` and ``request``.  The ``request`` is the current
SP 86 :term:`request` representing the denied action.  The ``context`` (if used in
87 the call signature) will be the instance of the
99edc5 88 :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the view to
CM 89 be called.
fab8c5 90
0db4a1 91 Both :meth:`pyramid.config.Configurator.add_notfound_view` and
CM 92 :class:`pyramid.view.notfound_view_config` can be used to automatically
93 redirect requests to slash-appended routes. See
94 :ref:`redirecting_to_slash_appended_routes` for examples.
95
cec2b0 96 Here's some sample code that implements a minimal :term:`Not Found View`
TL 97 callable:
fab8c5 98
CM 99 .. code-block:: python
601289 100    :linenos:
fab8c5 101
94b889 102    from pyramid.httpexceptions import HTTPNotFound
fab8c5 103
0db4a1 104    def notfound(request):
fab8c5 105        return HTTPNotFound()
CM 106
012b97 107 .. note::
M 108
8aa1c2 109    When a Not Found View callable is invoked, it is passed a :term:`request`.
SP 110    The ``exception`` attribute of the request will be an instance of the
111    :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the Not
112    Found View to be called.  The value of ``request.exception.message`` will be
113    a value explaining why the Not Found exception was raised.  This message has
114    different values depending on whether the ``pyramid.debug_notfound``
115    environment setting is true or false.
ff1213 116
0db4a1 117 .. note::
CM 118
8aa1c2 119    When a Not Found View callable accepts an argument list as described in
SP 120    :ref:`request_and_context_view_definitions`, the ``context`` passed as the
121    first argument to the view callable will be the
99edc5 122    :exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance.  If
CM 123    available, the resource context will still be available as
124    ``request.context``.
f6fb4b 125
MM 126 .. warning::
127
128    The :term:`Not Found View` callables are only invoked when a
129    :exc:`~pyramid.httpexceptions.HTTPNotFound` exception is raised. If the
130    exception is returned from a view then it will be treated as a regular
131    response object and it will not trigger the custom view.
8c56ae 132
CM 133 .. index::
c5f24b 134    single: forbidden view
fab8c5 135
7bc20e 136 .. _changing_the_forbidden_view:
CM 137
fab8c5 138 Changing the Forbidden View
CM 139 ---------------------------
140
e1a7e0 141 When :app:`Pyramid` can't authorize execution of a view based on the
8aa1c2 142 :term:`authorization policy` in use, it invokes a :term:`forbidden view`. The
SP 143 default forbidden response has a 403 status code and is very plain, but the
144 view which generates it can be overridden as necessary.
ff1213 145
e1a7e0 146 The :term:`forbidden view` callable is a view callable like any other.  The
8aa1c2 147 :term:`view configuration` which causes it to be a "forbidden" view consists of
SP 148 using the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the
a7fe30 149 :class:`pyramid.view.forbidden_view_config` decorator.
0ac818 150
a7fe30 151 For example, you can add a forbidden view by using the
CM 152 :meth:`pyramid.config.Configurator.add_forbidden_view` method to register a
153 forbidden view:
0ac818 154
e1a7e0 155 .. code-block:: python
CM 156    :linenos:
0ac818 157
439a02 158    def forbidden(request):
TL 159        return Response('forbidden')
0ac818 160
439a02 161    def main(globals, **settings):
TL 162        config = Configurator()
da004d 163        config.add_forbidden_view(forbidden)
0ac818 164
a7fe30 165 If instead you prefer to use decorators and a :term:`scan`, you can use the
CM 166 :class:`pyramid.view.forbidden_view_config` decorator to mark a view callable
167 as a forbidden view:
168
169 .. code-block:: python
170    :linenos:
171
172    from pyramid.view import forbidden_view_config
173
bce621 174    @forbidden_view_config()
a7fe30 175    def forbidden(request):
CM 176        return Response('forbidden')
177
178    def main(globals, **settings):
179       config = Configurator()
180       config.scan()
181
e1a7e0 182 Like any other view, the forbidden view must accept at least a ``request``
8aa1c2 183 parameter, or both ``context`` and ``request``.  If a forbidden view callable
SP 184 accepts both ``context`` and ``request``, the HTTP Exception is passed as
185 context. The ``context`` as found by the router when the view was denied (which
186 you normally would expect) is available as ``request.context``.  The
187 ``request`` is the  current :term:`request` representing the denied action.
13c923 188
CM 189 Here's some sample code that implements a minimal forbidden view:
fab8c5 190
CM 191 .. code-block:: python
601289 192    :linenos:
fab8c5 193
02d745 194    from pyramid.view import view_config
e1a7e0 195    from pyramid.response import Response
fab8c5 196
6103bf 197    def forbidden_view(request):
e1a7e0 198        return Response('forbidden')
fab8c5 199
012b97 200 .. note::
M 201
8aa1c2 202    When a forbidden view callable is invoked, it is passed a :term:`request`.
SP 203    The ``exception`` attribute of the request will be an instance of the
204    :exc:`~pyramid.httpexceptions.HTTPForbidden` exception that caused the
205    forbidden view to be called.  The value of ``request.exception.message``
206    will be a value explaining why the forbidden exception was raised, and
207    ``request.exception.result`` will be extended information about the
208    forbidden exception.  These messages have different values depending on
209    whether the ``pyramid.debug_authorization`` environment setting is true or
210    false.
fab8c5 211
f6fb4b 212 .. warning::
MM 213
214    The :term:`forbidden view` callables are only invoked when a
215    :exc:`~pyramid.httpexceptions.HTTPForbidden` exception is raised. If the
216    exception is returned from a view then it will be treated as a regular
217    response object and it will not trigger the custom view.
218
8c56ae 219 .. index::
74abc0 220    single: request factory
CM 221
222 .. _changing_the_request_factory:
223
224 Changing the Request Factory
225 ----------------------------
226
ee9769 227 Whenever :app:`Pyramid` handles a request from a :term:`WSGI` server, it
CM 228 creates a :term:`request` object based on the WSGI environment it has been
8aa1c2 229 passed.  By default, an instance of the :class:`pyramid.request.Request` class
SP 230 is created to represent the request object.
74abc0 231
8aa1c2 232 The class (a.k.a., "factory") that :app:`Pyramid` uses to create a request
SP 233 object instance can be changed by passing a ``request_factory`` argument to the
74abc0 234 constructor of the :term:`configurator`.  This argument can be either a
CM 235 callable or a :term:`dotted Python name` representing a callable.
236
237 .. code-block:: python
238    :linenos:
239
240    from pyramid.request import Request
241
242    class MyRequest(Request):
243        pass
244
245    config = Configurator(request_factory=MyRequest)
246
247 If you're doing imperative configuration, and you'd rather do it after you've
8aa1c2 248 already constructed a :term:`configurator`, it can also be registered via the
74abc0 249 :meth:`pyramid.config.Configurator.set_request_factory` method:
CM 250
251 .. code-block:: python
252    :linenos:
253
254    from pyramid.config import Configurator
255    from pyramid.request import Request
256
257    class MyRequest(Request):
258        pass
259
260    config = Configurator()
261    config.set_request_factory(MyRequest)
262
263 .. index::
9db1a1 264    single: request method
K 265
266 .. _adding_request_method:
267
8aa1c2 268 Adding Methods or Properties to a Request Object
SP 269 ------------------------------------------------
9db1a1 270
d49c69 271 .. versionadded:: 1.4
5b9c21 272
K 273 Since each Pyramid application can only have one :term:`request` factory,
8aa1c2 274 :ref:`changing the request factory <changing_the_request_factory>` is not that
SP 275 extensible, especially if you want to build composable features (e.g., Pyramid
276 add-ons and plugins).
9db1a1 277
K 278 A lazy property can be registered to the request object via the
8aa1c2 279 :meth:`pyramid.config.Configurator.add_request_method` API. This allows you to
SP 280 specify a callable that will be available on the request object, but will not
9db1a1 281 actually execute the function until accessed.
K 282
c7a06f 283 .. warning::
CM 284
285    This will silently override methods and properties from :term:`request
286    factory` that have the same name.
9db1a1 287
K 288 .. code-block:: python
289    :linenos:
290
291    from pyramid.config import Configurator
292
293    def total(request, *args):
294        return sum(args)
295
296    def prop(request):
edfc4f 297        print("getting the property")
9db1a1 298        return "the property"
K 299
300    config = Configurator()
301    config.add_request_method(total)
302    config.add_request_method(prop, reify=True)
303
8aa1c2 304 In the above example, ``total`` is added as a method. However, ``prop`` is
SP 305 added as a property and its result is cached per-request by setting
306 ``reify=True``. This way, we eliminate the overhead of running the function
307 multiple times.
9db1a1 308
a470ff 309 .. testsetup:: group1
SP 310
311    from pyramid.config import Configurator
312
313
314    def total(request, *args):
315        return sum(args)
316
317
318    def prop(request):
319        print("getting the property")
320        return "the property"
321
322
323
324    config = Configurator()
325    config.add_request_method(total)
326    config.add_request_method(prop, reify=True)
327    config.commit()
328
329    from pyramid.scripting import prepare
330    request = prepare(registry=config.registry)["request"]
331
332 .. doctest:: group1
333
9db1a1 334    >>> request.total(1, 2, 3)
K 335    6
336    >>> request.prop
337    getting the property
a470ff 338    'the property'
9db1a1 339    >>> request.prop
a470ff 340    'the property'
9db1a1 341
K 342 To not cache the result of ``request.prop``, set ``property=True`` instead of
343 ``reify=True``.
344
345 Here is an example of passing a class to ``Configurator.add_request_method``:
346
347 .. code-block:: python
348    :linenos:
349
350    from pyramid.config import Configurator
351    from pyramid.decorator import reify
352
353    class ExtraStuff(object):
354
355        def __init__(self, request):
356            self.request = request
357
358        def total(self, *args):
359            return sum(args)
360
361        # use @property if you don't want to cache the result
362        @reify
363        def prop(self):
edfc4f 364            print("getting the property")
9db1a1 365            return "the property"
K 366
367    config = Configurator()
368    config.add_request_method(ExtraStuff, 'extra', reify=True)
369
370 We attach and cache an object named ``extra`` to the ``request`` object.
371
a470ff 372 .. testsetup:: group2
SP 373
374    from pyramid.config import Configurator
375    from pyramid.decorator import reify
376
377    class ExtraStuff(object):
378
379        def __init__(self, request):
380            self.request = request
381
382        def total(self, *args):
383            return sum(args)
384
385        # use @property if you don't want to cache the result
386        @reify
387        def prop(self):
388            print("getting the property")
389            return "the property"
390
391    config = Configurator()
392    config.add_request_method(ExtraStuff, 'extra', reify=True)
393    config.commit()
394
395    from pyramid.scripting import prepare
396    request = prepare(registry=config.registry)["request"]
397
398 .. doctest:: group2
399
9db1a1 400    >>> request.extra.total(1, 2, 3)
K 401    6
402    >>> request.extra.prop
403    getting the property
a470ff 404    'the property'
9db1a1 405    >>> request.extra.prop
a470ff 406    'the property'
SP 407
9db1a1 408
K 409 .. index::
1236de 410    single: response factory
JA 411
412 .. _changing_the_response_factory:
413
414 Changing the Response Factory
8aa1c2 415 -----------------------------
1236de 416
807e94 417 .. versionadded:: 1.6
JA 418
8aa1c2 419 Whenever :app:`Pyramid` returns a response from a view, it creates a
1236de 420 :term:`response` object.  By default, an instance of the
JA 421 :class:`pyramid.response.Response` class is created to represent the response
422 object.
423
8aa1c2 424 The factory that :app:`Pyramid` uses to create a response object instance can
SP 425 be changed by passing a :class:`pyramid.interfaces.IResponseFactory` argument
426 to the constructor of the :term:`configurator`.  This argument can be either a
da5f5f 427 callable or a :term:`dotted Python name` representing a callable.
1236de 428
5de795 429 The factory takes a single positional argument, which is a :term:`Request`
da5f5f 430 object. The argument may be ``None``.
5de795 431
1236de 432 .. code-block:: python
JA 433    :linenos:
434
435    from pyramid.response import Response
436
437    class MyResponse(Response):
438        pass
439
32cb80 440    config = Configurator(response_factory=lambda r: MyResponse())
1236de 441
8aa1c2 442 If you're doing imperative configuration and you'd rather do it after you've
SP 443 already constructed a :term:`configurator`, it can also be registered via the
1236de 444 :meth:`pyramid.config.Configurator.set_response_factory` method:
JA 445
446 .. code-block:: python
447    :linenos:
448
449    from pyramid.config import Configurator
450    from pyramid.response import Response
451
452    class MyResponse(Response):
453        pass
454
455    config = Configurator()
32cb80 456    config.set_response_factory(lambda r: MyResponse())
1236de 457
8b5000 458 .. index::
SP 459    single: before render event
460    single: adding renderer globals
461
462 .. _beforerender_event:
1236de 463
8aa1c2 464 Using the Before Render Event
ac7a9a 465 -----------------------------
CM 466
467 Subscribers to the :class:`pyramid.events.BeforeRender` event may introspect
468 and modify the set of :term:`renderer globals` before they are passed to a
8aa1c2 469 :term:`renderer`.  This event object iself has a dictionary-like interface that
SP 470 can be used for this purpose.  For example:
ac7a9a 471
CM 472 .. code-block:: python
392a6c 473     :linenos:
ac7a9a 474
CM 475     from pyramid.events import subscriber
476     from pyramid.events import BeforeRender
477
478     @subscriber(BeforeRender)
479     def add_global(event):
480         event['mykey'] = 'foo'
481
8aa1c2 482 An object of this type is sent as an event just before a :term:`renderer` is
SP 483 invoked.
ac7a9a 484
8aa1c2 485 If a subscriber attempts to add a key that already exists in the renderer
ac7a9a 486 globals dictionary, a :exc:`KeyError` is raised.  This limitation is enforced
CM 487 because event subscribers do not possess any relative ordering.  The set of
488 keys added to the renderer globals dictionary by all
8aa1c2 489 :class:`pyramid.events.BeforeRender` subscribers and renderer globals factories
SP 490 must be unique.
ac7a9a 491
a31924 492 The dictionary returned from the view is accessible through the
JC 493 :attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`
2516df 494 event.
JC 495
8aa1c2 496 Suppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from your
SP 497 view callable, like so:
a31924 498
JC 499 .. code-block:: python
2516df 500    :linenos:
a31924 501
2516df 502    from pyramid.view import view_config
a31924 503
2516df 504    @view_config(renderer='some_renderer')
JC 505    def myview(request):
506        return {'mykey': 'somevalue', 'mykey2': 'somevalue2'}
507
508 :attr:`rendering_val` can be used to access these values from the
509 :class:`~pyramid.events.BeforeRender` object:
510
511 .. code-block:: python
512    :linenos:
513
514    from pyramid.events import subscriber
515    from pyramid.events import BeforeRender
516
517    @subscriber(BeforeRender)
518    def read_return(event):
519        # {'mykey': 'somevalue'} is returned from the view
520        print(event.rendering_val['mykey'])
a31924 521
ac7a9a 522 See the API documentation for the :class:`~pyramid.events.BeforeRender` event
CM 523 interface at :class:`pyramid.interfaces.IBeforeRender`.
74abc0 524
CM 525 .. index::
526    single: response callback
527
528 .. _using_response_callbacks:
529
530 Using Response Callbacks
531 ------------------------
532
533 Unlike many other web frameworks, :app:`Pyramid` does not eagerly create a
534 global response object.  Adding a :term:`response callback` allows an
f9896b 535 application to register an action to be performed against whatever response
CM 536 object is returned by a view, usually in order to mutate the response.
74abc0 537
CM 538 The :meth:`pyramid.request.Request.add_response_callback` method is used to
539 register a response callback.
540
541 A response callback is a callable which accepts two positional parameters:
542 ``request`` and ``response``.  For example:
543
544 .. code-block:: python
545    :linenos:
546
547    def cache_callback(request, response):
548        """Set the cache_control max_age for the response"""
549        if request.exception is not None:
550            response.cache_control.max_age = 360
551    request.add_response_callback(cache_callback)
552
8aa1c2 553 No response callback is called if an unhandled exception happens in application
SP 554 code, or if the response object returned by a :term:`view callable` is invalid.
555 Response callbacks *are*, however, invoked when a :term:`exception view` is
556 rendered successfully.  In such a case, the :attr:`request.exception` attribute
557 of the request when it enters a response callback will be an exception object
558 instead of its default value of ``None``.
74abc0 559
CM 560 Response callbacks are called in the order they're added
8aa1c2 561 (first-to-most-recently-added).  All response callbacks are called *before* the
SP 562 :class:`~pyramid.events.NewResponse` event is sent.  Errors raised by response
563 callbacks are not handled specially.  They will be propagated to the caller of
564 the :app:`Pyramid` router application.
74abc0 565
CM 566 A response callback has a lifetime of a *single* request.  If you want a
567 response callback to happen as the result of *every* request, you must
8aa1c2 568 re-register the callback into every new request (perhaps within a subscriber of
SP 569 a :class:`~pyramid.events.NewRequest` event).
74abc0 570
CM 571 .. index::
572    single: finished callback
573
574 .. _using_finished_callbacks:
575
576 Using Finished Callbacks
577 ------------------------
578
579 A :term:`finished callback` is a function that will be called unconditionally
8aa1c2 580 by the :app:`Pyramid` :term:`router` at the very end of request processing. A
SP 581 finished callback can be used to perform an action at the end of a request
74abc0 582 unconditionally.
CM 583
584 The :meth:`pyramid.request.Request.add_finished_callback` method is used to
585 register a finished callback.
586
8aa1c2 587 A finished callback is a callable which accepts a single positional parameter:
SP 588 ``request``.  For example:
74abc0 589
CM 590 .. code-block:: python
591    :linenos:
592
ae6d08 593    import logging
74abc0 594
ae6d08 595    log = logging.getLogger(__name__)
RS 596
597    def log_callback(request):
598        """Log information at the end of request"""
599        log.debug('Request is finished.')
600    request.add_finished_callback(log_callback)
74abc0 601
4dc751 602 Finished callbacks are called in the order they're added
8aa1c2 603 (first-to-most-recently-added).  Finished callbacks (unlike a :term:`response
SP 604 callback`) are *always* called, even if an exception happens in application
605 code that prevents a response from being generated.
74abc0 606
8aa1c2 607 The set of finished callbacks associated with a request are called *very late*
SP 608 in the processing of that request; they are essentially the very last thing
609 called by the :term:`router` before a request "ends". They are called after
610 response processing has already occurred in a top-level ``finally:`` block
611 within the router request processing code.  As a result, mutations performed to
612 the ``request`` provided to a finished callback will have no meaningful effect,
613 because response processing will have already occurred, and the request's scope
614 will expire almost immediately after all finished callbacks have been
615 processed.
74abc0 616
8aa1c2 617 Errors raised by finished callbacks are not handled specially.  They will be
SP 618 propagated to the caller of the :app:`Pyramid` router application.
74abc0 619
CM 620 A finished callback has a lifetime of a *single* request.  If you want a
621 finished callback to happen as the result of *every* request, you must
8aa1c2 622 re-register the callback into every new request (perhaps within a subscriber of
SP 623 a :class:`~pyramid.events.NewRequest` event).
8c56ae 624
CM 625 .. index::
c5f24b 626    single: traverser
def444 627
80a25e 628 .. _changing_the_traverser:
CM 629
630 Changing the Traverser
631 ----------------------
632
e1a7e0 633 The default :term:`traversal` algorithm that :app:`Pyramid` uses is explained
CM 634 in :ref:`traversal_algorithm`.  Though it is rarely necessary, this default
8aa1c2 635 algorithm can be swapped out selectively for a different traversal pattern via
SP 636 configuration.
80a25e 637
e1a7e0 638 .. code-block:: python
80a25e 639    :linenos:
CM 640
748aad 641    from pyramid.config import Configurator
e1a7e0 642    from myapp.traversal import Traverser
748aad 643    config = Configurator()
13305e 644    config.add_traverser(Traverser)
e1a7e0 645
CM 646 In the example above, ``myapp.traversal.Traverser`` is assumed to be a class
647 that implements the following interface:
80a25e 648
CM 649 .. code-block:: python
650    :linenos:
651
652    class Traverser(object):
653        def __init__(self, root):
654            """ Accept the root object returned from the root factory """
655
acc776 656        def __call__(self, request):
80a25e 657            """ Return a dictionary with (at least) the keys ``root``,
CM 658            ``context``, ``view_name``, ``subpath``, ``traversed``,
659            ``virtual_root``, and ``virtual_root_path``.  These values are
fb6a5c 660            typically the result of a resource tree traversal.  ``root``
CM 661            is the physical root object, ``context`` will be a resource
80a25e 662            object, ``view_name`` will be the view name used (a Unicode
CM 663            name), ``subpath`` will be a sequence of Unicode names that
664            followed the view name but were not traversed, ``traversed``
665            will be a sequence of Unicode names that were traversed
666            (including the virtual root path, if any) ``virtual_root``
fb6a5c 667            will be a resource object representing the virtual root (or the
80a25e 668            physical root if traversal was not performed), and
CM 669            ``virtual_root_path`` will be a sequence representing the
670            virtual root path (a sequence of Unicode names) or None if
671            traversal was not performed.
672
673            Extra keys for special purpose functionality can be added as
674            necessary.
675
676            All values returned in the dictionary will be made available
677            as attributes of the ``request`` object.
678            """
679
680 More than one traversal algorithm can be active at the same time.  For
e1a7e0 681 instance, if your :term:`root factory` returns more than one type of object
8aa1c2 682 conditionally, you could claim that an alternative traverser adapter is "for"
e1a7e0 683 only one particular class or interface.  When the root factory returned an
CM 684 object that implemented that class or interface, a custom traverser would be
8aa1c2 685 used.  Otherwise the default traverser would be used.  For example:
80a25e 686
e1a7e0 687 .. code-block:: python
80a25e 688    :linenos:
CM 689
e1a7e0 690    from myapp.traversal import Traverser
CM 691    from myapp.resources import MyRoot
748aad 692    from pyramid.config import Configurator
CM 693    config = Configurator()
13305e 694    config.add_traverser(Traverser, MyRoot)
e1a7e0 695
CM 696 If the above stanza was added to a Pyramid ``__init__.py`` file's ``main``
8aa1c2 697 function, :app:`Pyramid` would use the ``myapp.traversal.Traverser`` only when
SP 698 the application :term:`root factory` returned an instance of the
fb6a5c 699 ``myapp.resources.MyRoot`` object.  Otherwise it would use the default
fd5ae9 700 :app:`Pyramid` traverser to do traversal.
80a25e 701
8c56ae 702 .. index::
8aa1c2 703    single: URL generator
e1a7e0 704
CM 705 .. _changing_resource_url:
8c56ae 706
fb90f0 707 Changing How :meth:`pyramid.request.Request.resource_url` Generates a URL
CM 708 -------------------------------------------------------------------------
80a25e 709
fb6a5c 710 When you add a traverser as described in :ref:`changing_the_traverser`, it's
fb90f0 711 often convenient to continue to use the
CM 712 :meth:`pyramid.request.Request.resource_url` API.  However, since the way
8aa1c2 713 traversal is done will have been modified, the URLs it generates by default may
SP 714 be incorrect when used against resources derived from your custom traverser.
80a25e 715
cb8e34 716 If you've added a traverser, you can change how
fb90f0 717 :meth:`~pyramid.request.Request.resource_url` generates a URL for a specific
c51896 718 type of resource by adding a call to
125ea4 719 :meth:`pyramid.config.Configurator.add_resource_url_adapter`.
c51896 720
CM 721 For example:
80a25e 722
e1a7e0 723 .. code-block:: python
80a25e 724    :linenos:
CM 725
c51896 726    from myapp.traversal import ResourceURLAdapter
e1a7e0 727    from myapp.resources import MyRoot
80a25e 728
95129f 729    config.add_resource_url_adapter(ResourceURLAdapter, MyRoot)
e1a7e0 730
8aa1c2 731 In the above example, the ``myapp.traversal.ResourceURLAdapter`` class will be
SP 732 used to provide services to :meth:`~pyramid.request.Request.resource_url` any
733 time the :term:`resource` passed to ``resource_url`` is of the class
c51896 734 ``myapp.resources.MyRoot``.  The ``resource_iface`` argument ``MyRoot``
CM 735 represents the type of interface that must be possessed by the resource for
736 this resource url factory to be found.  If the ``resource_iface`` argument is
8aa1c2 737 omitted, this resource URL adapter will be used for *all* resources.
80a25e 738
e2b679 739 The API that must be implemented by a class that provides
c51896 740 :class:`~pyramid.interfaces.IResourceURL` is as follows:
80a25e 741
CM 742 .. code-block:: python
743   :linenos:
744
c51896 745   class MyResourceURL(object):
CM 746       """ An adapter which provides the virtual and physical paths of a
747           resource
ca866f 748       """
c51896 749       def __init__(self, resource, request):
8aa1c2 750           """ Accept the resource and request and set self.physical_path and
SP 751           self.virtual_path """
c51896 752           self.virtual_path =  some_function_of(resource, request)
44563d 753           self.virtual_path_tuple =  some_function_of(resource, request)
c51896 754           self.physical_path =  some_other_function_of(resource, request)
44563d 755           self.physical_path_tuple =  some_function_of(resource, request)
80a25e 756
e1a7e0 757 The default context URL generator is available for perusal as the class
c51896 758 :class:`pyramid.traversal.ResourceURL` in the `traversal module
cd8ac8 759 <https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
e1a7e0 760 :term:`Pylons` GitHub Pyramid repository.
7aa7fd 761
8aa1c2 762 See :meth:`pyramid.config.Configurator.add_resource_url_adapter` for more
SP 763 information.
c51896 764
74abc0 765 .. index::
d868ff 766    single: IResponse
6ce1e0 767    single: special view responses
df15ed 768
d868ff 769 .. _using_iresponse:
df15ed 770
d868ff 771 Changing How Pyramid Treats View Responses
CM 772 ------------------------------------------
df15ed 773
40dbf4 774 .. versionadded:: 1.1
TL 775
d868ff 776 It is possible to control how Pyramid treats the result of calling a view
CM 777 callable on a per-type basis by using a hook involving
078412 778 :meth:`pyramid.config.Configurator.add_response_adapter` or the
MH 779 :class:`~pyramid.response.response_adapter` decorator.
df15ed 780
8aa1c2 781 Pyramid, in various places, adapts the result of calling a view callable to the
SP 782 :class:`~pyramid.interfaces.IResponse` interface to ensure that the object
783 returned by the view callable is a "true" response object.  The vast majority
784 of time, the result of this adaptation is the result object itself, as view
785 callables written by "civilians" who read the narrative documentation contained
786 in this manual will always return something that implements the
787 :class:`~pyramid.interfaces.IResponse` interface.  Most typically, this will be
788 an instance of the :class:`pyramid.response.Response` class or a subclass. If a
789 civilian returns a non-Response object from a view callable that isn't
790 configured to use a :term:`renderer`, they will typically expect the router to
d868ff 791 raise an error.  However, you can hook Pyramid in such a way that users can
CM 792 return arbitrary values from a view callable by providing an adapter which
793 converts the arbitrary return value into something that implements
794 :class:`~pyramid.interfaces.IResponse`.
df15ed 795
d868ff 796 For example, if you'd like to allow view callables to return bare string
8aa1c2 797 objects (without requiring a :term:`renderer` to convert a string to a response
SP 798 object), you can register an adapter which converts the string to a Response:
df15ed 799
d868ff 800 .. code-block:: python
CM 801    :linenos:
802
803    from pyramid.response import Response
804
805    def string_response_adapter(s):
806        response = Response(s)
807        return response
808
809    # config is an instance of pyramid.config.Configurator
810
1a6fc7 811    config.add_response_adapter(string_response_adapter, str)
d868ff 812
8aa1c2 813 Likewise, if you want to be able to return a simplified kind of response object
SP 814 from view callables, you can use the IResponse hook to register an adapter to
815 the more complex IResponse interface:
d868ff 816
CM 817 .. code-block:: python
818    :linenos:
819
820    from pyramid.response import Response
821
822    class SimpleResponse(object):
823        def __init__(self, body):
824            self.body = body
825
826    def simple_response_adapter(simple_response):
827        response = Response(simple_response.body)
828        return response
829
830    # config is an instance of pyramid.config.Configurator
831
1a6fc7 832    config.add_response_adapter(simple_response_adapter, SimpleResponse)
d868ff 833
CM 834 If you want to implement your own Response object instead of using the
835 :class:`pyramid.response.Response` object in any capacity at all, you'll have
8aa1c2 836 to make sure that the object implements every attribute and method outlined in
1ca5b3 837 :class:`pyramid.interfaces.IResponse` and you'll have to ensure that it uses
3702ab 838 ``zope.interface.implementer(IResponse)`` as a class decorator.
d868ff 839
15ac15 840 .. code-block:: python
MM 841    :linenos:
842
d868ff 843    from pyramid.interfaces import IResponse
1ca5b3 844    from zope.interface import implementer
d868ff 845
1ca5b3 846    @implementer(IResponse)
d868ff 847    class MyResponse(object):
8aa1c2 848        # ... an implementation of every method and attribute
d868ff 849        # documented in IResponse should follow ...
CM 850
851 When an alternate response object implementation is returned by a view
852 callable, if that object asserts that it implements
853 :class:`~pyramid.interfaces.IResponse` (via
1ca5b3 854 ``zope.interface.implementer(IResponse)``) , an adapter needn't be registered
d868ff 855 for the object; Pyramid will use it directly.
CM 856
857 An IResponse adapter for ``webob.Response`` (as opposed to
858 :class:`pyramid.response.Response`) is registered by Pyramid by default at
859 startup time, as by their nature, instances of this class (and instances of
860 subclasses of the class) will natively provide IResponse.  The adapter
861 registered for ``webob.Response`` simply returns the response object.
df15ed 862
8aa1c2 863 Instead of using :meth:`pyramid.config.Configurator.add_response_adapter`, you
SP 864 can use the :class:`pyramid.response.response_adapter` decorator:
1f901a 865
CM 866 .. code-block:: python
867    :linenos:
868
869    from pyramid.response import Response
870    from pyramid.response import response_adapter
871
872    @response_adapter(str)
873    def string_response_adapter(s):
874        response = Response(s)
875        return response
876
877 The above example, when scanned, has the same effect as:
878
879 .. code-block:: python
880
881    config.add_response_adapter(string_response_adapter, str)
882
883 The :class:`~pyramid.response.response_adapter` decorator will have no effect
884 until activated by a :term:`scan`.
885
df15ed 886 .. index::
c5e83c 887    single: view mapper
81a833 888
522d7d 889 .. _using_a_view_mapper:
81a833 890
c5e83c 891 Using a View Mapper
CM 892 -------------------
81a833 893
c5e83c 894 The default calling conventions for view callables are documented in the
1130ec 895 :ref:`views_chapter` chapter.  You can change the way users define view
879bb5 896 callables by employing a :term:`view mapper`.
c5e83c 897
CM 898 A view mapper is an object that accepts a set of keyword arguments and which
899 returns a callable.  The returned callable is called with the :term:`view
8aa1c2 900 callable` object.  The returned callable should itself return another callable
SP 901 which can be called with the "internal calling protocol" ``(context,
c5e83c 902 request)``.
CM 903
904 You can use a view mapper in a number of ways:
905
8aa1c2 906 - by setting a ``__view_mapper__`` attribute (which is the view mapper object)
SP 907   on the view callable itself
c5e83c 908
8aa1c2 909 - by passing the mapper object to :meth:`pyramid.config.Configurator.add_view`
SP 910   (or its declarative and decorator equivalents) as the ``mapper`` argument
c5e83c 911
8aa1c2 912 - by registering a *default* view mapper
c5e83c 913
CM 914 Here's an example of a view mapper that emulates (somewhat) a Pylons
915 "controller".  The mapper is initialized with some keyword arguments.  Its
916 ``__call__`` method accepts the view object (which will be a class).  It uses
8aa1c2 917 the ``attr`` keyword argument it is passed to determine which attribute should
SP 918 be used as an action method.  The wrapper method it returns accepts ``(context,
919 request)`` and returns the result of calling the action method with keyword
920 arguments implied by the :term:`matchdict` after popping the ``action`` out of
921 it.  This somewhat emulates the Pylons style of calling action methods with
922 routing parameters pulled out of the route matching dict as keyword arguments.
81a833 923
CM 924 .. code-block:: python
925    :linenos:
926
c5e83c 927    # framework
81a833 928
c5e83c 929    class PylonsControllerViewMapper(object):
CM 930        def __init__(self, **kw):
931            self.kw = kw
81a833 932
c5e83c 933        def __call__(self, view):
CM 934            attr = self.kw['attr']
935            def wrapper(context, request):
936                matchdict = request.matchdict.copy()
937                matchdict.pop('action', None)
46eccc 938                inst = view(request)
c5e83c 939                meth = getattr(inst, attr)
CM 940                return meth(**matchdict)
941            return wrapper
81a833 942
c5e83c 943    class BaseController(object):
CM 944        __view_mapper__ = PylonsControllerViewMapper
81a833 945
c5e83c 946 A user might make use of these framework components like so:
81a833 947
CM 948 .. code-block:: python
949    :linenos:
950
c5e83c 951    # user application
CM 952
d868ff 953    from pyramid.response import Response
d7f259 954    from pyramid.config import Configurator
2fa576 955    import pyramid_handlers
cfb2b5 956    from wsgiref.simple_server import make_server
81a833 957
c5e83c 958    class MyController(BaseController):
CM 959        def index(self, id):
960            return Response(id)
81a833 961
c5e83c 962    if __name__ == '__main__':
CM 963        config = Configurator()
2fa576 964        config.include(pyramid_handlers)
c5e83c 965        config.add_handler('one', '/{id}', MyController, action='index')
CM 966        config.add_handler('two', '/{action}/{id}', MyController)
cfb2b5 967        server.make_server('0.0.0.0', 8080, config.make_wsgi_app())
CM 968        server.serve_forever()
81a833 969
cae85d 970 The :meth:`pyramid.config.Configurator.set_view_mapper` method can be used to
CM 971 set a *default* view mapper (overriding the superdefault view mapper used by
972 Pyramid itself).
250c02 973
8aa1c2 974 A *single* view registration can use a view mapper by passing the mapper as the
SP 975 ``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.
250c02 976
c5e83c 977 .. index::
74abc0 978    single: configuration decorator
81d3b5 979
6bc662 980 .. _registering_configuration_decorators:
CM 981
7200cb 982 Registering Configuration Decorators
CM 983 ------------------------------------
7aa7fd 984
8aa1c2 985 Decorators such as :class:`~pyramid.view.view_config` don't change the behavior
SP 986 of the functions or classes they're decorating.  Instead when a :term:`scan` is
987 performed, a modified version of the function or class is registered with
988 :app:`Pyramid`.
7aa7fd 989
e1a7e0 990 You may wish to have your own decorators that offer such behaviour. This is
8aa1c2 991 possible by using the :term:`Venusian` package in the same way that it is used
SP 992 by :app:`Pyramid`.
7aa7fd 993
e1a7e0 994 By way of example, let's suppose you want to write a decorator that registers
CM 995 the function it wraps with a :term:`Zope Component Architecture` "utility"
996 within the :term:`application registry` provided by :app:`Pyramid`. The
997 application registry and the utility inside the registry is likely only to be
998 available once your application's configuration is at least partially
999 completed. A normal decorator would fail as it would be executed before the
1000 configuration had even begun.
7aa7fd 1001
8aa1c2 1002 However, using :term:`Venusian`, the decorator could be written as follows:
7aa7fd 1003
CW 1004 .. code-block:: python
1005    :linenos:
1006
1007    import venusian
7200cb 1008    from mypackage.interfaces import IMyUtility
879bb5 1009
7aa7fd 1010    class registerFunction(object):
879bb5 1011
c70c74 1012        def __init__(self, path):
7aa7fd 1013            self.path = path
CW 1014
c70c74 1015        def register(self, scanner, name, wrapped):
780b6f 1016            registry = scanner.config.registry
7200cb 1017            registry.getUtility(IMyUtility).register(
879bb5 1018                self.path, wrapped)
CZ 1019
c70c74 1020        def __call__(self, wrapped):
7200cb 1021            venusian.attach(wrapped, self.register)
7aa7fd 1022            return wrapped
879bb5 1023
8aa1c2 1024 This decorator could then be used to register functions throughout your code:
7aa7fd 1025
CW 1026 .. code-block:: python
1027    :linenos:
1028
1029    @registerFunction('/some/path')
1030    def my_function():
8aa1c2 1031        do_stuff()
7aa7fd 1032
8aa1c2 1033 However, the utility would only be looked up when a :term:`scan` was performed,
SP 1034 enabling you to set up the utility in advance:
7aa7fd 1035
CW 1036 .. code-block:: python
1037    :linenos:
1038
1ca5b3 1039    from zope.interface import implementer
CM 1040
10f1b5 1041    from wsgiref.simple_server import make_server
d7f259 1042    from pyramid.config import Configurator
879bb5 1043    from mypackage.interfaces import IMyUtility
7aa7fd 1044
1ca5b3 1045    @implementer(IMyUtility)
7aa7fd 1046    class UtilityImplementation:
CW 1047
1048        def __init__(self):
8aa1c2 1049            self.registrations = {}
7aa7fd 1050
879bb5 1051        def register(self, path, callable_):
8aa1c2 1052            self.registrations[path] = callable_
7aa7fd 1053
CW 1054    if __name__ == '__main__':
1055        config = Configurator()
1056        config.registry.registerUtility(UtilityImplementation())
1057        config.scan()
1058        app = config.make_wsgi_app()
10f1b5 1059        server = make_server('0.0.0.0', 8080, app)
CM 1060        server.serve_forever()
7aa7fd 1061
51498c 1062 For full details, please read the :ref:`Venusian documentation <venusian:venusian>`.
SP 1063
6bc662 1064
131132 1065 .. _registering_tweens:
CM 1066
04e6bf 1067 Registering Tweens
AH 1068 ------------------
131132 1069
40dbf4 1070 .. versionadded:: 1.2
TL 1071    Tweens
131132 1072
05f610 1073 A :term:`tween` (a contraction of the word "between") is a bit of code that
CM 1074 sits between the Pyramid router's main request handling function and the
1075 upstream WSGI component that uses :app:`Pyramid` as its "app".  This is a
8aa1c2 1076 feature that may be used by Pyramid framework extensions to provide, for
05f610 1077 example, Pyramid-specific view timing support bookkeeping code that examines
131132 1078 exceptions before they are returned to the upstream WSGI application.  Tweens
8aa1c2 1079 behave a bit like :term:`WSGI` :term:`middleware`, but they have the benefit of
04e6bf 1080 running in a context in which they have access to the Pyramid :term:`request`,
8aa1c2 1081 :term:`response`, and :term:`application registry`, as well as the Pyramid
04e6bf 1082 rendering machinery.
131132 1083
04e6bf 1084 Creating a Tween
AH 1085 ~~~~~~~~~~~~~~~~
539646 1086
8aa1c2 1087 To create a tween, you must write a "tween factory".  A tween factory must be a
SP 1088 globally importable callable which accepts two arguments: ``handler`` and
1089 ``registry``.  ``handler`` will be either the main Pyramid request handling
1090 function or another tween.  ``registry`` will be the Pyramid :term:`application
1091 registry` represented by this Configurator.  A tween factory must return the
1092 tween (a callable object) when it is called.
131132 1093
04e6bf 1094 A tween is called with a single argument, ``request``, which is the
8aa1c2 1095 :term:`request` created by Pyramid's router when it receives a WSGI request. A
SP 1096 tween should return a :term:`response`, usually the one generated by the
04e6bf 1097 downstream Pyramid application.
bf669a 1098
04e6bf 1099 You can write the tween factory as a simple closure-returning function:
AH 1100
1101 .. code-block:: python
392a6c 1102     :linenos:
04e6bf 1103
AH 1104     def simple_tween_factory(handler, registry):
1105         # one-time configuration code goes here
1106
1107         def simple_tween(request):
1108             # code to be executed for each request before
1109             # the actual application code goes here
1110
1111             response = handler(request)
1112
1113             # code to be executed for each request after
1114             # the actual application code goes here
1115
1116             return response
1117
fab44e 1118         return simple_tween
04e6bf 1119
a0ef13 1120 Alternatively, the tween factory can be a class with the ``__call__`` magic
bf669a 1121 method:
04e6bf 1122
AH 1123 .. code-block:: python
392a6c 1124     :linenos:
04e6bf 1125
AH 1126     class simple_tween_factory(object):
fbcce7 1127         def __init__(self, handler, registry):
04e6bf 1128             self.handler = handler
AH 1129             self.registry = registry
1130
1131             # one-time configuration code goes here
1132
1133         def __call__(self, request):
1134             # code to be executed for each request before
1135             # the actual application code goes here
1136
1137             response = self.handler(request)
1138
1139             # code to be executed for each request after
1140             # the actual application code goes here
1141
1142             return response
1143
8aa1c2 1144 You should avoid mutating any state on the tween instance. The tween is invoked
SP 1145 once per request and any shared mutable state needs to be carefully handled to
1146 avoid any race conditions.
2c096b 1147
04e6bf 1148 The closure style performs slightly better and enables you to conditionally
AH 1149 omit the tween from the request processing pipeline (see the following timing
1150 tween example), whereas the class style makes it easier to have shared mutable
8aa1c2 1151 state and allows subclassing.
04e6bf 1152
AH 1153 Here's a complete example of a tween that logs the time spent processing each
1154 request:
131132 1155
CM 1156 .. code-block:: python
392a6c 1157     :linenos:
539646 1158
CM 1159     # in a module named myapp.tweens
131132 1160
CM 1161     import time
1162     from pyramid.settings import asbool
1163     import logging
1164
1165     log = logging.getLogger(__name__)
1166
1167     def timing_tween_factory(handler, registry):
1168         if asbool(registry.settings.get('do_timing')):
1169             # if timing support is enabled, return a wrapper
1170             def timing_tween(request):
1171                 start = time.time()
1172                 try:
8d1533 1173                     response = handler(request)
131132 1174                 finally:
CM 1175                     end = time.time()
1176                     log.debug('The request took %s seconds' %
1177                               (end - start))
8d1533 1178                 return response
131132 1179             return timing_tween
CM 1180         # if timing support is not enabled, return the original
1181         # handler
1182         return handler
539646 1183
CM 1184 In the above example, the tween factory defines a ``timing_tween`` tween and
1185 returns it if ``asbool(registry.settings.get('do_timing'))`` is true.  It
8aa1c2 1186 otherwise simply returns the handler which it was given.  The
SP 1187 ``registry.settings`` attribute is a handle to the deployment settings provided
1188 by the user (usually in an ``.ini`` file).  In this case, if the user has
1189 defined a ``do_timing`` setting and that setting is ``True``, the user has said
1190 they want to do timing, so the tween factory returns the timing tween; it
1191 otherwise just returns the handler it has been provided, preventing any timing.
539646 1192
CM 1193 The example timing tween simply records the start time, calls the downstream
1194 handler, logs the number of seconds consumed by the downstream handler, and
1195 returns the response.
1196
1197 Registering an Implicit Tween Factory
1198 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1199
1200 Once you've created a tween factory, you can register it into the implicit
1201 tween chain using the :meth:`pyramid.config.Configurator.add_tween` method
1202 using its :term:`dotted Python name`.
1203
991a1a 1204 Here's an example of registering a tween factory as an "implicit" tween in a
CI 1205 Pyramid application:
539646 1206
CM 1207 .. code-block:: python
392a6c 1208     :linenos:
539646 1209
131132 1210     from pyramid.config import Configurator
CM 1211     config = Configurator()
539646 1212     config.add_tween('myapp.tweens.timing_tween_factory')
131132 1213
539646 1214 Note that you must use a :term:`dotted Python name` as the first argument to
CM 1215 :meth:`pyramid.config.Configurator.add_tween`; this must point at a tween
1216 factory.  You cannot pass the tween factory object itself to the method: it
8aa1c2 1217 must be :term:`dotted Python name` that points to a globally importable object.
SP 1218 In the above example, we assume that a ``timing_tween_factory`` tween factory
1219 was defined in a module named ``myapp.tweens``, so the tween factory is
1220 importable as ``myapp.tweens.timing_tween_factory``.
539646 1221
8aa1c2 1222 When you use :meth:`pyramid.config.Configurator.add_tween`, you're instructing
SP 1223 the system to use your tween factory at startup time unless the user has
1224 provided an explicit tween list in their configuration.  This is what's meant
1225 by an "implicit" tween.  A user can always elect to supply an explicit tween
1226 list, reordering or disincluding implicitly added tweens.  See
539646 1227 :ref:`explicit_tween_ordering` for more information about explicit tween
CM 1228 ordering.
131132 1229
8aa1c2 1230 If more than one call to :meth:`pyramid.config.Configurator.add_tween` is made
SP 1231 within a single application configuration, the tweens will be chained together
1232 at application startup time.  The *first* tween factory added via ``add_tween``
1233 will be called with the Pyramid exception view tween factory as its ``handler``
1234 argument, then the tween factory added directly after that one will be called
1235 with the result of the first tween factory as its ``handler`` argument, and so
1236 on, ad infinitum until all tween factories have been called. The Pyramid router
1237 will use the outermost tween produced by this chain (the tween generated by the
1238 very last tween factory added) as its request handler function.  For example:
131132 1239
05f610 1240 .. code-block:: python
392a6c 1241     :linenos:
131132 1242
05f610 1243     from pyramid.config import Configurator
CM 1244
1245     config = Configurator()
1246     config.add_tween('myapp.tween_factory1')
1247     config.add_tween('myapp.tween_factory2')
1248
8aa1c2 1249 The above example will generate an implicit tween chain that looks like this::
05f610 1250
CM 1251     INGRESS (implicit)
1252     myapp.tween_factory2
1253     myapp.tween_factory1
1254     pyramid.tweens.excview_tween_factory (implicit)
1255     MAIN (implicit)
1256
539646 1257 Suggesting Implicit Tween Ordering
CM 1258 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1259
05f610 1260 By default, as described above, the ordering of the chain is controlled
CM 1261 entirely by the relative ordering of calls to
1262 :meth:`pyramid.config.Configurator.add_tween`.  However, the caller of
8aa1c2 1263 ``add_tween`` can provide an optional hint that can influence the implicit
SP 1264 tween chain ordering by supplying ``under`` or ``over`` (or both) arguments to
1265 :meth:`~pyramid.config.Configurator.add_tween`.  These hints are only used when
1266 an explicit tween ordering is not used. See :ref:`explicit_tween_ordering` for
1267 a description of how to set an explicit tween ordering.
05f610 1268
CM 1269 Allowable values for ``under`` or ``over`` (or both) are:
1270
8aa1c2 1271 - ``None`` (the default),
05f610 1272
8aa1c2 1273 - a :term:`dotted Python name` to a tween factory: a string representing the
SP 1274   predicted dotted name of a tween factory added in a call to ``add_tween`` in
1275   the same configuration session,
05f610 1276
8aa1c2 1277 - one of the constants :attr:`pyramid.tweens.MAIN`,
SP 1278   :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`, or
05f610 1279
8aa1c2 1280 - an iterable of any combination of the above. This allows the user to specify
9ec766 1281   fallbacks if the desired tween is not included, as well as compatibility
MM 1282   with multiple other tweens.
1283
8aa1c2 1284 Effectively, ``over`` means "closer to the request ingress than" and ``under``
SP 1285 means "closer to the main Pyramid application than". You can think of an onion
1286 with outer layers over the inner layers, the application being under all the
1287 layers at the center.
05f610 1288
CM 1289 For example, the following call to
8aa1c2 1290 :meth:`~pyramid.config.Configurator.add_tween` will attempt to place the tween
SP 1291 factory represented by ``myapp.tween_factory`` directly "above" (in ``ptweens``
1292 order) the main Pyramid request handler.
05f610 1293
CM 1294 .. code-block:: python
1295    :linenos:
1296
1297    import pyramid.tweens
1298
1299    config.add_tween('myapp.tween_factory', over=pyramid.tweens.MAIN)
1300
8aa1c2 1301 The above example will generate an implicit tween chain that looks like this::
05f610 1302
CM 1303     INGRESS (implicit)
1304     pyramid.tweens.excview_tween_factory (implicit)
1305     myapp.tween_factory
1306     MAIN (implicit)
1307
1308 Likewise, calling the following call to
8aa1c2 1309 :meth:`~pyramid.config.Configurator.add_tween` will attempt to place this tween
SP 1310 factory "above" the main handler but "below" a separately added tween factory:
05f610 1311
CM 1312 .. code-block:: python
1313    :linenos:
1314
1315    import pyramid.tweens
1316
1317    config.add_tween('myapp.tween_factory1',
1318                     over=pyramid.tweens.MAIN)
1319    config.add_tween('myapp.tween_factory2',
1320                     over=pyramid.tweens.MAIN,
1321                     under='myapp.tween_factory1')
1322
8aa1c2 1323 The above example will generate an implicit tween chain that looks like this::
05f610 1324
CM 1325     INGRESS (implicit)
1326     pyramid.tweens.excview_tween_factory (implicit)
1327     myapp.tween_factory1
1328     myapp.tween_factory2
1329     MAIN (implicit)
1330
1331 Specifying neither ``over`` nor ``under`` is equivalent to specifying
1332 ``under=INGRESS``.
1333
9ec766 1334 If all options for ``under`` (or ``over``) cannot be found in the current
MM 1335 configuration, it is an error. If some options are specified purely for
8aa1c2 1336 compatibilty with other tweens, just add a fallback of ``MAIN`` or ``INGRESS``.
SP 1337 For example, ``under=('someothertween', 'someothertween2', INGRESS)``. This
1338 constraint will require the tween to be located under the ``someothertween``
1339 tween, the ``someothertween2`` tween, and ``INGRESS``. If any of these is not
1340 in the current configuration, this constraint will only organize itself based
1341 on the tweens that are present.
05f610 1342
be46da 1343 .. _explicit_tween_ordering:
CM 1344
1345 Explicit Tween Ordering
1346 ~~~~~~~~~~~~~~~~~~~~~~~
1347
8aa1c2 1348 Implicit tween ordering is obviously only best-effort.  Pyramid will attempt to
SP 1349 provide an implicit order of tweens as best it can using hints provided by
1350 calls to :meth:`~pyramid.config.Configurator.add_tween`.  But because it's only
1351 best-effort, if very precise tween ordering is required, the only surefire way
1352 to get it is to use an explicit tween order.  The deploying user can override
1353 the implicit tween inclusion and ordering implied by calls to
05f610 1354 :meth:`~pyramid.config.Configurator.add_tween` entirely by using the
CM 1355 ``pyramid.tweens`` settings value.  When used, this settings value must be a
8aa1c2 1356 list of Python dotted names which will override the ordering (and inclusion) of
SP 1357 tween factories in the implicit tween chain.  For example:
131132 1358
CM 1359 .. code-block:: ini
1360    :linenos:
1361
1362    [app:main]
1363    use = egg:MyApp
1364    pyramid.reload_templates = true
1365    pyramid.debug_authorization = false
1366    pyramid.debug_notfound = false
1367    pyramid.debug_routematch = false
1368    pyramid.debug_templates = true
05f610 1369    pyramid.tweens = myapp.my_cool_tween_factory
CM 1370                     pyramid.tweens.excview_tween_factory
131132 1371
CM 1372 In the above configuration, calls made during configuration to
1373 :meth:`pyramid.config.Configurator.add_tween` are ignored, and the user is
1374 telling the system to use the tween factories he has listed in the
8aa1c2 1375 ``pyramid.tweens`` configuration setting (each is a :term:`dotted Python name`
SP 1376 which points to a tween factory) instead of any tween factories added via
1377 :meth:`pyramid.config.Configurator.add_tween`.  The *first* tween factory in
1378 the ``pyramid.tweens`` list will be used as the producer of the effective
131132 1379 :app:`Pyramid` request handling function; it will wrap the tween factory
8aa1c2 1380 declared directly "below" it, ad infinitum.  The "main" Pyramid request handler
SP 1381 is implicit, and always "at the bottom".
131132 1382
012b97 1383 .. note::
M 1384
8aa1c2 1385    Pyramid's own :term:`exception view` handling logic is implemented as a
SP 1386    tween factory function: :func:`pyramid.tweens.excview_tween_factory`.  If
1387    Pyramid exception view handling is desired, and tween factories are
131132 1388    specified via the ``pyramid.tweens`` configuration setting, the
CM 1389    :func:`pyramid.tweens.excview_tween_factory` function must be added to the
1390    ``pyramid.tweens`` configuration setting list explicitly.  If it is not
1391    present, Pyramid will not perform exception view handling.
1392
be46da 1393 Tween Conflicts and Ordering Cycles
CM 1394 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1395
8aa1c2 1396 Pyramid will prevent the same tween factory from being added to the tween chain
SP 1397 more than once using configuration conflict detection.  If you wish to add the
1398 same tween factory more than once in a configuration, you should either: (a)
1399 use a tween factory that is a separate globally importable instance object from
1400 the factory that it conflicts with; (b) use a function or class as a tween
1401 factory with the same logic as the other tween factory it conflicts with, but
1402 with a different ``__name__`` attribute; or (c) call
157c29 1403 :meth:`pyramid.config.Configurator.commit` between calls to
CM 1404 :meth:`pyramid.config.Configurator.add_tween`.
131132 1405
05f610 1406 If a cycle is detected in implicit tween ordering when ``over`` and ``under``
8aa1c2 1407 are used in any call to ``add_tween``, an exception will be raised at startup
05f610 1408 time.
CM 1409
be46da 1410 Displaying Tween Ordering
CM 1411 ~~~~~~~~~~~~~~~~~~~~~~~~~
1412
8aa1c2 1413 The ``ptweens`` command-line utility can be used to report the current implict
SP 1414 and explicit tween chains used by an application.  See
05f610 1415 :ref:`displaying_tweens`.
0196b2 1416
CM 1417 .. _registering_thirdparty_predicates:
1418
8aa1c2 1419 Adding a Third Party View, Route, or Subscriber Predicate
95f766 1420 ---------------------------------------------------------
0196b2 1421
40dbf4 1422 .. versionadded:: 1.4
5664c4 1423
95f766 1424 .. _view_and_route_predicates:
CM 1425
1426 View and Route Predicates
1427 ~~~~~~~~~~~~~~~~~~~~~~~~~
1428
8aa1c2 1429 View and route predicates used during configuration allow you to narrow the set
SP 1430 of circumstances under which a view or route will match.  For example, the
1431 ``request_method`` view predicate can be used to ensure a view callable is only
1432 invoked when the request's method is ``POST``:
0196b2 1433
CM 1434 .. code-block:: python
1435
1436     @view_config(request_method='POST')
1437     def someview(request):
1438         ...
1439
1440 Likewise, a similar predicate can be used as a *route* predicate:
1441
1442 .. code-block:: python
1443
1444     config.add_route('name', '/foo', request_method='POST')
1445
8aa1c2 1446 Many other built-in predicates exists (``request_param``, and others).  You can
SP 1447 add third-party predicates to the list of available predicates by using one of
1448 :meth:`pyramid.config.Configurator.add_view_predicate` or
0196b2 1449 :meth:`pyramid.config.Configurator.add_route_predicate`.  The former adds a
CM 1450 view predicate, the latter a route predicate.
1451
1452 When using one of those APIs, you pass a *name* and a *factory* to add a
1453 predicate during Pyramid's configuration stage.  For example:
1454
1455 .. code-block:: python
1456
1457     config.add_view_predicate('content_type', ContentTypePredicate)
1458
1459 The above example adds a new predicate named ``content_type`` to the list of
1460 available predicates for views.  This will allow the following view
1461 configuration statement to work:
1462
1463 .. code-block:: python
1464    :linenos:
1465
1466    @view_config(content_type='File')
1467    def aview(request): ...
1468
1469 The first argument to :meth:`pyramid.config.Configurator.add_view_predicate`,
1470 the name, is a string representing the name that is expected to be passed to
1471 ``view_config`` (or its imperative analogue ``add_view``).
1472
d71aca 1473 The second argument is a view or route predicate factory, or a :term:`dotted
BJR 1474 Python name` which refers to a view or route predicate factory.  A view or
1475 route predicate factory is most often a class with a constructor
8aa1c2 1476 (``__init__``), a ``text`` method, a ``phash`` method, and a ``__call__``
d71aca 1477 method. For example:
0196b2 1478
CM 1479 .. code-block:: python
392a6c 1480     :linenos:
0196b2 1481
CM 1482     class ContentTypePredicate(object):
1483         def __init__(self, val, config):
cff71c 1484             self.val = val
0196b2 1485
CM 1486         def text(self):
1487             return 'content_type = %s' % (self.val,)
1488
1489         phash = text
1490
1491         def __call__(self, context, request):
ad05d1 1492             return request.content_type == self.val
0196b2 1493
CM 1494 The constructor of a predicate factory takes two arguments: ``val`` and
1495 ``config``.  The ``val`` argument will be the argument passed to
8aa1c2 1496 ``view_config`` (or ``add_view``).  In the example above, it will be the string
SP 1497 ``File``.  The second argument, ``config``, will be the Configurator instance
1498 at the time of configuration.
0196b2 1499
8aa1c2 1500 The ``text`` method must return a string.  It should be useful to describe the
SP 1501 behavior of the predicate in error messages.
0196b2 1502
8aa1c2 1503 The ``phash`` method must return a string or a sequence of strings.  It's most
SP 1504 often the same as ``text``, as long as ``text`` uniquely describes the
1505 predicate's name and the value passed to the constructor.  If ``text`` is more
1506 general, or doesn't describe things that way, ``phash`` should return a string
1507 with the name and the value serialized.  The result of ``phash`` is not seen in
1508 output anywhere, it just informs the uniqueness constraints for view
1509 configuration.
0196b2 1510
ad05d1 1511 The ``__call__`` method differs depending on whether the predicate is used as
MM 1512 a :term:`view predicate` or a :term:`route predicate`:
0196b2 1513
ad05d1 1514 - When used as a route predicate, the ``__call__`` signature is
MM 1515   ``(info, request)``. The ``info`` object is a dictionary containing two
1516   keys: ``match`` and ``route``. ``info['match']`` is the matchdict containing
1517   the patterns matched in the route pattern. ``info['route']`` is the
1518   :class:`pyramid.interfaces.IRoute` object for the current route.
1519
1520 - When used as a view predicate, the ``__call__`` signature is
1521   ``(context, request)``. The ``context`` is the result of :term:`traversal`
1522   performed using either the route's :term:`root factory` or the app's
1523   :term:`default root factory`.
1524
1525 In both cases the ``__call__`` method is expected to return ``True`` or
1526 ``False``.
1527
1528 It is possible to use the same predicate factory as both a view predicate and
1529 as a route predicate, but they'll need to handle the ``info`` or ``context``
1530 argument specially (many predicates do not need this argument) and you'll need
1531 to call ``add_view_predicate`` and ``add_route_predicate`` separately with
1532 the same factory.
0196b2 1533
95f766 1534 .. _subscriber_predicates:
CM 1535
1536 Subscriber Predicates
1537 ~~~~~~~~~~~~~~~~~~~~~
1538
8aa1c2 1539 Subscriber predicates work almost exactly like view and route predicates. They
SP 1540 narrow the set of circumstances in which a subscriber will be called. There are
1541 several minor differences between a subscriber predicate and a view or route
1542 predicate:
95f766 1543
CM 1544 - There are no default subscriber predicates.  You must register one to use
1545   one.
1546
8aa1c2 1547 - The ``__call__`` method of a subscriber predicate accepts a single ``event``
SP 1548   object instead of a ``context`` and a ``request``.
95f766 1549
CM 1550 - Not every subscriber predicate can be used with every event type.  Some
1551   subscriber predicates will assume a certain event type.
1552
1553 Here's an example of a subscriber predicate that can be used in conjunction
46d505 1554 with a subscriber that subscribes to the :class:`pyramid.events.NewRequest`
95f766 1555 event type.
CM 1556
1557 .. code-block:: python
392a6c 1558     :linenos:
95f766 1559
CM 1560     class RequestPathStartsWith(object):
1561         def __init__(self, val, config):
1562             self.val = val
1563
1564         def text(self):
1565             return 'path_startswith = %s' % (self.val,)
1566
1567         phash = text
1568
1569         def __call__(self, event):
1570             return event.request.path.startswith(self.val)
1571
4c583e 1572 Once you've created a subscriber predicate, it may be registered via
95f766 1573 :meth:`pyramid.config.Configurator.add_subscriber_predicate`.  For example:
CM 1574
1575 .. code-block:: python
1576
1577     config.add_subscriber_predicate(
1578         'request_path_startswith', RequestPathStartsWith)
1579
1580 Once a subscriber predicate is registered, you can use it in a call to
1581 :meth:`pyramid.config.Configurator.add_subscriber` or to
8aa1c2 1582 :class:`pyramid.events.subscriber`.  Here's an example of using the previously
SP 1583 registered ``request_path_startswith`` predicate in a call to
95f766 1584 :meth:`~pyramid.config.Configurator.add_subscriber`:
CM 1585
1586 .. code-block:: python
392a6c 1587     :linenos:
95f766 1588
CM 1589     # define a subscriber in your code
1590
1591     def yosubscriber(event):
1592         event.request.yo = 'YO!'
1593
1594     # and at configuration time
1595
8aa1c2 1596     config.add_subscriber(yosubscriber, NewRequest,
95f766 1597            request_path_startswith='/add_yo')
CM 1598
1599 Here's the same subscriber/predicate/event-type combination used via
1600 :class:`~pyramid.events.subscriber`.
1601
1602 .. code-block:: python
392a6c 1603     :linenos:
95f766 1604
CM 1605     from pyramid.events import subscriber
1606
1607     @subscriber(NewRequest, request_path_startswith='/add_yo')
1608     def yosubscriber(event):
1609         event.request.yo = 'YO!'
1610
8aa1c2 1611 In either of the above configurations, the ``yosubscriber`` callable will only
SP 1612 be called if the request path starts with ``/add_yo``.  Otherwise the event
1613 subscriber will not be called.
95f766 1614
CM 1615 Note that the ``request_path_startswith`` subscriber you defined can be used
1616 with events that have a ``request`` attribute, but not ones that do not.  So,
1617 for example, the predicate can be used with subscribers registered for
1618 :class:`pyramid.events.NewRequest` and :class:`pyramid.events.ContextFound`
1619 events, but it cannot be used with subscribers registered for
8aa1c2 1620 :class:`pyramid.events.ApplicationCreated` because the latter type of event has
SP 1621 no ``request`` attribute.  The point being, unlike route and view predicates,
1622 not every type of subscriber predicate will necessarily be applicable for use
1623 in every subscriber registration.  It is not the responsibility of the
1624 predicate author to make every predicate make sense for every event type; it is
1625 the responsibility of the predicate consumer to use predicates that make sense
1626 for a particular event type registration.
fdd1f8 1627
6fb44f 1628
fdd1f8 1629 .. index::
MM 1630    single: view derivers
1631
1632 .. _view_derivers:
1633
1634 View Derivers
1635 -------------
1636
a11694 1637 .. versionadded:: 1.7
MM 1638
fdd1f8 1639 Every URL processed by :app:`Pyramid` is matched against a custom view
MM 1640 pipeline. See :ref:`router_chapter` for how this works. The view pipeline
6fb44f 1641 itself is built from the user-supplied :term:`view callable`, which is then
fdd1f8 1642 composed with :term:`view derivers <view deriver>`. A view deriver is a
MM 1643 composable element of the view pipeline which is used to wrap a view with
1644 added functionality. View derivers are very similar to the ``decorator``
6fb44f 1645 argument to :meth:`pyramid.config.Configurator.add_view`, except that they have
fdd1f8 1646 the option to execute for every view in the application.
MM 1647
a11694 1648 It is helpful to think of a :term:`view deriver` as middleware for views.
MM 1649 Unlike tweens or WSGI middleware which are scoped to the application itself,
6fb44f 1650 a view deriver is invoked once per view in the application, and can use
a11694 1651 configuration options from the view to customize its behavior.
MM 1652
fdd1f8 1653 Built-in View Derivers
MM 1654 ~~~~~~~~~~~~~~~~~~~~~~
1655
6fb44f 1656 There are several built-in view derivers that :app:`Pyramid` will automatically
a11694 1657 apply to any view. Below they are defined in order from furthest to closest to
fdd1f8 1658 the user-defined :term:`view callable`:
a11694 1659
MM 1660 ``secured_view``
1661
6fb44f 1662   Enforce the ``permission`` defined on the view. This element is a no-op if no
SP 1663   permission is defined. Note there will always be a permission defined if a
1664   default permission was assigned via
e8c66a 1665   :meth:`pyramid.config.Configurator.set_default_permission` unless the
MM 1666   view is an :term:`exception view`.
a11694 1667
a3db3c 1668   This element will also output useful debugging information when
MM 1669   ``pyramid.debug_authorization`` is enabled.
6b35eb 1670
MM 1671 ``csrf_view``
1672
1673   Used to check the CSRF token provided in the request. This element is a
f2bc0e 1674   no-op if ``require_csrf`` view option is not ``True``. Note there will
MM 1675   always be a ``require_csrf`` option if a default value was assigned via
e8c66a 1676   :meth:`pyramid.config.Configurator.set_default_csrf_options` unless
MM 1677   the view is an :term:`exception view`.
a3db3c 1678
a11694 1679 ``owrapped_view``
MM 1680
1681   Invokes the wrapped view defined by the ``wrapper`` option.
1682
1683 ``http_cached_view``
1684
1685   Applies cache control headers to the response defined by the ``http_cache``
6fb44f 1686   option. This element is a no-op if the ``pyramid.prevent_http_cache`` setting
a11694 1687   is enabled or the ``http_cache`` option is ``None``.
MM 1688
1689 ``decorated_view``
1690
1691   Wraps the view with the decorators from the ``decorator`` option.
1692
1693 ``rendered_view``
1694
1695   Adapts the result of the :term:`view callable` into a :term:`response`
1696   object. Below this point the result may be any Python object.
fdd1f8 1697
MM 1698 ``mapped_view``
1699
1700   Applies the :term:`view mapper` defined by the ``mapper`` option or the
1701   application's default view mapper to the :term:`view callable`. This
1702   is always the closest deriver to the user-defined view and standardizes the
1703   view pipeline interface to accept ``(context, request)`` from all previous
1704   view derivers.
1705
c231d8 1706 .. warning::
MM 1707
1708    Any view derivers defined ``under`` the ``rendered_view`` are not
1709    guaranteed to receive a valid response object. Rather they will receive the
1710    result from the :term:`view mapper` which is likely the original response
1711    returned from the view. This is possibly a dictionary for a renderer but it
1712    may be any Python object that may be adapted into a response.
1713
fdd1f8 1714 Custom View Derivers
MM 1715 ~~~~~~~~~~~~~~~~~~~~
1716
6fb44f 1717 It is possible to define custom view derivers which will affect all views in an
SP 1718 application. There are many uses for this, but most will likely be centered
1719 around monitoring and security. In order to register a custom :term:`view
1720 deriver`, you should create a callable that conforms to the
1721 :class:`pyramid.interfaces.IViewDeriver` interface, and then register it with
35e632 1722 your application using :meth:`pyramid.config.Configurator.add_view_deriver`.
e8c66a 1723 The callable should accept the ``view`` to be wrapped and the ``info`` object
MM 1724 which is an instance of :class:`pyramid.interfaces.IViewDeriverInfo`.
35e632 1725 For example, below is a callable that can provide timing information for the
MM 1726 view pipeline:
fdd1f8 1727
MM 1728 .. code-block:: python
1729    :linenos:
1730
1731    import time
1732
1733    def timing_view(view, info):
16f989 1734        if info.options.get('timed'):
CM 1735            def wrapper_view(context, request):
1736                start = time.time()
1737                response = view(context, request)
1738                end = time.time()
1739                response.headers['X-View-Performance'] = '%.3f' % (end - start,)
1740                return response
1741            return wrapper_view
1742        return view
1743
1744    timing_view.options = ('timed',)
fdd1f8 1745
c231d8 1746    config.add_view_deriver(timing_view)
fdd1f8 1747
16f989 1748 The setting of ``timed`` on the timing_view signifies to Pyramid that ``timed``
CM 1749 is a valid ``view_config`` keyword argument now.  The ``timing_view`` custom
1750 view deriver as registered above will only be active for any view defined with
1751 a ``timed=True`` value passed as one of its ``view_config`` keywords.
1752
1753 For example, this view configuration will *not* be a timed view:
1754
1755 .. code-block:: python
1756    :linenos:
1757
1758    @view_config(route_name='home')
1759    def home(request):
1760        return Response('Home')
1761
1762 But this view *will* have timing information added to the response headers:
1763
1764 .. code-block:: python
1765    :linenos:
1766
1767    @view_config(route_name='home', timed=True)
1768    def home(request):
1769        return Response('Home')
1770
fdd1f8 1771 View derivers are unique in that they have access to most of the options
MM 1772 passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what
6fb44f 1773 to do, and they have a chance to affect every view in the application.
fdd1f8 1774
e8c66a 1775 .. _exception_view_derivers:
MM 1776
1777 Exception Views and View Derivers
1778 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1779
1780 A :term:`view deriver` has the opportunity to wrap any view, including
1781 an :term:`exception view`. In general this is fine, but certain view derivers
1782 may wish to avoid doing certain things when handling exceptions. For example,
1783 the ``csrf_view`` and ``secured_view`` built-in view derivers will not perform
1784 security checks on exception views unless explicitly told to do so.
1785
1786 You can check for ``info.exception_only`` on the
1787 :class:`pyramid.interfaces.IViewDeriverInfo` object when wrapping the view
1788 to determine whether you are wrapping an exception view or a normal view.
1789
fdd1f8 1790 Ordering View Derivers
MM 1791 ~~~~~~~~~~~~~~~~~~~~~~
1792
6fb44f 1793 By default, every new view deriver is added between the ``decorated_view`` and
SP 1794 ``rendered_view`` built-in derivers. It is possible to customize this ordering
1795 using the ``over`` and ``under`` options. Each option can use the names of
1796 other view derivers in order to specify an ordering. There should rarely be a
c231d8 1797 reason to worry about the ordering of the derivers except when the deriver
MM 1798 depends on other operations in the view pipeline.
6fb44f 1799
SP 1800 Both ``over`` and ``under`` may also be iterables of constraints. For either
1801 option, if one or more constraints was defined, at least one must be satisfied,
1802 else a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may
1803 be used to define fallback constraints if another deriver is missing.
c231d8 1804
MM 1805 Two sentinel values exist, :attr:`pyramid.viewderivers.INGRESS` and
1806 :attr:`pyramid.viewderivers.VIEW`, which may be used when specifying
1807 constraints at the edges of the view pipeline. For example, to add a deriver
1808 at the start of the pipeline you may use ``under=INGRESS``.
fdd1f8 1809
a11694 1810 It is not possible to add a view deriver under the ``mapped_view`` as the
fdd1f8 1811 :term:`view mapper` is intimately tied to the signature of the user-defined
MM 1812 :term:`view callable`. If you simply need to know what the original view
1813 callable was, it can be found as ``info.original_view`` on the provided
1814 :class:`pyramid.interfaces.IViewDeriverInfo` object passed to every view
1815 deriver.
a11694 1816
MM 1817 .. warning::
1818
c231d8 1819    The default constraints for any view deriver are ``over='rendered_view'``
MM 1820    and ``under='decorated_view'``. When escaping these constraints you must
1821    take care to avoid cyclic dependencies between derivers. For example, if
1822    you want to add a new view deriver before ``secured_view`` then
1823    simply specifying ``over='secured_view'`` is not enough, because the
1824    default is also under ``decorated view`` there will be an unsatisfiable
1825    cycle. You must specify a valid ``under`` constraint as well, such as
1826    ``under=INGRESS`` to fall between INGRESS and ``secured_view`` at the
1827    beginning of the view pipeline.