From e4b931a67455f14d84d415be49e6596d06cc0a42 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 9 Mar 2016 00:46:59 -0600 Subject: add options support to view derivers exposed a new IViewDeriver api with an optional ``options`` list to expose support for new kwargs that may be passed to config.add_view --- docs/api/interfaces.rst | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index de2a664a4..635d3c5b6 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -91,3 +91,9 @@ Other Interfaces .. autointerface:: ICacheBuster :members: + + .. autointerface:: IViewDeriver + :members: + + .. autointerface:: IViewDeriverInfo + :members: -- cgit v1.2.3 From b4147ba4b34b13eaf32f064e9827da733ff6ab7c Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 9 Mar 2016 01:01:58 -0600 Subject: add "view deriver" to the glossary --- docs/glossary.rst | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index bbc86db41..9e068a18c 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -1092,3 +1092,8 @@ Glossary A technique used when serving a cacheable static asset in order to force a client to query the new version of the asset. See :ref:`cache_busting` for more information. + + view deriver + A view deriver is a composable component of the view pipeline which is + used to create a :term:`view callable`. A view deriver is a callable + implementing the :class:`pyramid.interfaces.IViewDeriver` interface. -- cgit v1.2.3 From 05b2b50706cd303c28233a321ef3dcc2e45486be Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 13 Mar 2016 12:32:03 -0700 Subject: minor update to request processing diagram --- docs/_static/pyramid_request_processing.graffle | 60 ++++++++++++------------ docs/_static/pyramid_request_processing.png | Bin 122854 -> 123953 bytes docs/_static/pyramid_request_processing.svg | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) (limited to 'docs') diff --git a/docs/_static/pyramid_request_processing.graffle b/docs/_static/pyramid_request_processing.graffle index 71319610b..16b360543 100644 --- a/docs/_static/pyramid_request_processing.graffle +++ b/docs/_static/pyramid_request_processing.graffle @@ -53,7 +53,7 @@ Creator Steve Piercy DisplayScale - 1 0/72 in = 1 0/72 in + 1 0/72 in = 1.0000 in GraphDocumentVersion 8 GraphicsList @@ -84,8 +84,8 @@ 0 Points - {344.41667175292969, 402.88506673894034} - {375.5, 402.27232108797347} + {344.41668319702148, 402.88506673894034} + {375.5, 402.77232108797347} Style @@ -113,7 +113,7 @@ Tail ID - 169428 + 169509 @@ -243,11 +243,11 @@ Bounds - {{238.8333613077798, 284.99999999999994}, {105.66668701171875, 18.656048080136394}} + {{238.74999618530273, 284.99999999999994}, {105.75002924601222, 18.656048080136394}} Class ShapedGraphic ID - 169425 + 169506 Magnets {0, 1} @@ -296,11 +296,11 @@ Bounds - {{238.75000762939453, 412.15071036499205}, {105.66666412353516, 18.656048080136394}} + {{238.74999618530273, 412.15071036499205}, {105.66668701171875, 18.656048080136394}} Class ShapedGraphic ID - 169426 + 169507 Magnets {0, 1} @@ -349,11 +349,11 @@ Bounds - {{238.75000762939453, 303.65604172230951}, {105.66666412353516, 18.656048080136394}} + {{238.74999618530273, 303.65604172230951}, {105.66668701171875, 18.656048080136394}} Class ShapedGraphic ID - 169427 + 169508 Magnets {0, 1} @@ -402,11 +402,11 @@ Bounds - {{238.75000762939453, 393.55704269887212}, {105.66666412353516, 18.656048080136394}} + {{238.74999618530273, 393.55704269887212}, {105.66668701171875, 18.656048080136394}} Class ShapedGraphic ID - 169428 + 169509 Magnets {0, 1} @@ -453,11 +453,11 @@ Bounds - {{238.75000762939453, 374.90099016834085}, {105.66666412353516, 18.656048080136394}} + {{238.74999618530273, 374.90099016834085}, {105.66668701171875, 18.656048080136394}} Class ShapedGraphic ID - 169429 + 169510 Magnets {0, 1} @@ -504,11 +504,11 @@ Bounds - {{238.75000762939453, 341.36561209044055}, {105.66666412353516, 33.089282989501953}} + {{238.74999618530273, 341.36561209044055}, {105.66668701171875, 33.089282989501953}} Class ShapedGraphic ID - 169430 + 169511 Magnets {0, 1} @@ -555,11 +555,11 @@ Bounds - {{238.75000762939453, 322.26348241170439}, {105.66666412353516, 18.656048080136394}} + {{238.74999618530273, 322.26348241170439}, {105.66668701171875, 18.656048080136394}} Class ShapedGraphic ID - 169431 + 169512 Magnets {0, 1} @@ -606,7 +606,7 @@ ID - 169424 + 169505 Layer 0 @@ -1094,7 +1094,7 @@ 0 Points - {238.75000762939462, 430.80675844512831} + {238.74999618530282, 430.80675844512831} {207.66666666666765, 385.656005859375} Style @@ -1123,7 +1123,7 @@ Tail ID - 169426 + 169507 Info 6 @@ -1144,7 +1144,7 @@ 0 Points - {239.33336141608385, 285.57837549845181} + {239.25039065750093, 285.57837549845181} {207.66666666666777, 353.07514659563753} Style @@ -1173,7 +1173,7 @@ Tail ID - 169425 + 169506 Info 6 @@ -1515,7 +1515,7 @@ {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc -\f0\fs20 \cf0 view} +\f0\fs20 \cf0 view deriver} VerticalPad 0 @@ -1742,7 +1742,7 @@ Bounds - {{375.5, 391}, {105.66666412353516, 22.544642175946908}} + {{375.5, 391.5}, {105.66666412353516, 22.544642175946908}} Class ShapedGraphic ID @@ -9637,7 +9637,7 @@ MasterSheets ModificationDate - 2014-11-23 07:19:11 +0000 + 2016-03-13 08:04:48 +0000 Modifier Steve Piercy NotesVisible @@ -9732,15 +9732,15 @@ SidebarWidth 163 VisibleRegion - {{-231, -226}, {1037, 1186}} + {{152.25, 226.5}, {255.75, 292.75}} Zoom - 1 + 4 ZoomValues Request Processing - 1 - 2 + 4 + 8 diff --git a/docs/_static/pyramid_request_processing.png b/docs/_static/pyramid_request_processing.png index 2fbb1e164..c684255fa 100644 Binary files a/docs/_static/pyramid_request_processing.png and b/docs/_static/pyramid_request_processing.png differ diff --git a/docs/_static/pyramid_request_processing.svg b/docs/_static/pyramid_request_processing.svg index 21bbcb532..d32d5c5bc 100644 --- a/docs/_static/pyramid_request_processing.svg +++ b/docs/_static/pyramid_request_processing.svg @@ -1,3 +1,3 @@ -2014-11-23 07:19ZRequest Processingno exceptionsmiddleware ingress tween ingresstraversalContextFoundtween egressresponse callbacksfinished callbacksmiddleware egressBeforeRenderRequest ProcessingLegendeventcallbackviewexternal process (middleware, tween)internal processview pipelinepredicatesview lookuproute predicatesURL dispatchNewRequestNewResponseview mapper ingressviewview mapper egressresponse adapterdecorators ingressdecorators egressauthorization +2016-03-13 08:04ZRequest Processingno exceptionsmiddleware ingress tween ingresstraversalContextFoundtween egressresponse callbacksfinished callbacksmiddleware egressBeforeRenderRequest ProcessingLegendeventcallbackview deriverexternal process (middleware, tween)internal processview pipelinepredicatesview lookuproute predicatesURL dispatchNewRequestNewResponseview mapper ingressviewview mapper egressresponse adapterdecorators ingressdecorators egressauthorization -- cgit v1.2.3 From 7fc181d89e9553b152618066490d1fb659d45e13 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 13 Mar 2016 16:24:53 -0500 Subject: add examples of view derivers to the glossary --- docs/glossary.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index 9e068a18c..8928254f7 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -1097,3 +1097,5 @@ Glossary A view deriver is a composable component of the view pipeline which is used to create a :term:`view callable`. A view deriver is a callable implementing the :class:`pyramid.interfaces.IViewDeriver` interface. + Examples of builtin derivers including view mapper, the permission + checker, and applying a renderer to a dictionary returned from the view. -- cgit v1.2.3 From fdd1f8352fc341bc60e0b7d32dadd2b4109a2b41 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 22:08:04 -0500 Subject: first cut at documenting view derivers --- docs/narr/extconfig.rst | 1 + docs/narr/hooks.rst | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) (limited to 'docs') diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst index fee8d0d3a..af7d0a349 100644 --- a/docs/narr/extconfig.rst +++ b/docs/narr/extconfig.rst @@ -259,6 +259,7 @@ Pre-defined Phases - :meth:`pyramid.config.Configurator.add_route_predicate` - :meth:`pyramid.config.Configurator.add_subscriber_predicate` - :meth:`pyramid.config.Configurator.add_view_predicate` +- :meth:`pyramid.config.Configurator.add_view_deriver` - :meth:`pyramid.config.Configurator.set_authorization_policy` - :meth:`pyramid.config.Configurator.set_default_permission` - :meth:`pyramid.config.Configurator.set_view_mapper` diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 7ff119b53..13daed1fc 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1547,3 +1547,143 @@ in every subscriber registration. It is not the responsibility of the predicate author to make every predicate make sense for every event type; it is the responsibility of the predicate consumer to use predicates that make sense for a particular event type registration. + +.. index:: + single: view derivers + +.. _view_derivers: + +View Derivers +------------- + +Every URL processed by :app:`Pyramid` is matched against a custom view +pipeline. See :ref:`router_chapter` for how this works. The view pipeline +itself is built from the user-supplied :term:`view callable` which is then +composed with :term:`view derivers `. A view deriver is a +composable element of the view pipeline which is used to wrap a view with +added functionality. View derivers are very similar to the ``decorator`` +argument to :meth:`pyramid.config.Configurator.add_view` except that they have +the option to execute for every view in the application. + +Built-in View Derivers +~~~~~~~~~~~~~~~~~~~~~~ + +There are several builtin view derivers that :app:`Pyramid` will automatically +apply to any view. They are defined in order from closest to furthest from +the user-defined :term:`view callable`: + +``mapped_view`` + + Applies the :term:`view mapper` defined by the ``mapper`` option or the + application's default view mapper to the :term:`view callable`. This + is always the closest deriver to the user-defined view and standardizes the + view pipeline interface to accept ``(context, request)`` from all previous + view derivers. + +``decorated_view`` + + Wraps the view with the decorators from the ``decorator`` option. + +``http_cached_view`` + + Applies cache control headers to the response defined by the ``http_cache`` + option. This element is a noop if the ``pyramid.prevent_http_cache`` setting + is enabled or the ``http_cache`` option is ``None``. + +``owrapped_view`` + + Invokes the wrapped view defined by the ``wrapper`` option. + +``secured_view`` + + Enforce the ``permission`` defined on the view. This element is a noop if + no permission is defined. Note there will always be a permission defined + if a default permission was assigned via + :meth:`pyramid.config.Configurator.set_default_permission`. + +``authdebug_view`` + + Used to output useful debugging information when + ``pyramid.debug_authorization`` is enabled. This element is a noop otherwise. + +Custom View Derivers +~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.7 + +It is possible to define custom view derivers which will affect all views in +an application. There are many uses for this but most will likely be centered +around monitoring and security. In order to register a custom +:term:`view deriver` you should create a callable that conforms to the +:class:`pyramid.interfaces.IViewDeriver` interface. For example, below +is a callable that can provide timing information for the view pipeline: + +.. code-block:: python + :linenos: + + import time + + def timing_view(view, info): + def wrapper_view(context, request): + start = time.time() + response = view(context, request) + end = time.time() + response.headers['X-View-Performance'] = '%.3f' % (end - start,) + return wrapper_view + + config.add_view_deriver('timing_view', timing_view) + +View derivers are unique in that they have access to most of the options +passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what +to do and they have a chance to affect every view in the application. + +Let's look at one more example which will protect views by requiring a CSRF +token unless ``disable_csrf=True`` is passed to the view: + +.. code-block:: python + :linenos: + + from pyramid.session import check_csrf_token + + def require_csrf_view(view, info): + wrapper_view = view + if not info.options.get('disable_csrf', False): + def wrapper_view(context, request): + if request.method == 'POST': + check_csrf_token(request) + return view(context, request) + return wrapper_view + + require_csrf_view.options = ('disable_csrf',) + + config.add_view_deriver('require_csrf_view', require_csrf_view) + + def myview(request): + return 'protected' + + def my_unprotected_view(request): + return 'unprotected' + + config.add_view(myview, name='safe', renderer='string') + config.add_view(my_unprotected_, name='unsafe', disable_csrf=True, renderer='string') + +Navigating to ``/safe`` with a POST request will then fail when the call to +:func:`pyramid.session.check_csrf_token` raises a +:class:`pyramid.exceptions.BadCSRFToken` exception. However, ``/unsafe`` will +not error. + +Ordering View Derivers +~~~~~~~~~~~~~~~~~~~~~~ + +By default, every new view deriver is added between the ``decorated_view`` +and ``mapped_view`` built-in derivers. It is possible to customize this +ordering using the ``over`` and ``under`` options. Each option can use the +names of other view derivers in order to specify an ordering. There should +rarely be a reason to worry about the ordering of the derivers. + +It is not possible to add a deriver OVER the ``mapped_view`` as the +:term:`view mapper` is intimately tied to the signature of the user-defined +:term:`view callable`. If you simply need to know what the original view +callable was, it can be found as ``info.original_view`` on the provided +:class:`pyramid.interfaces.IViewDeriverInfo` object passed to every view +deriver. -- cgit v1.2.3 From 64bf7eec9b868fbc113341c7f5675c063aea002b Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 22:35:19 -0500 Subject: use the implicit name in the doc examples --- docs/narr/hooks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 13daed1fc..3f66f4988 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1631,7 +1631,7 @@ is a callable that can provide timing information for the view pipeline: response.headers['X-View-Performance'] = '%.3f' % (end - start,) return wrapper_view - config.add_view_deriver('timing_view', timing_view) + config.add_view_deriver(timing_view) View derivers are unique in that they have access to most of the options passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what @@ -1656,7 +1656,7 @@ token unless ``disable_csrf=True`` is passed to the view: require_csrf_view.options = ('disable_csrf',) - config.add_view_deriver('require_csrf_view', require_csrf_view) + config.add_view_deriver(require_csrf_view) def myview(request): return 'protected' -- cgit v1.2.3 From a0945399b24fb38607107a55b12b7997723de2a0 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 23:25:10 -0500 Subject: do not guess at the name of the view deriver without further discussion --- docs/narr/hooks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 3f66f4988..e3843cfbd 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1631,7 +1631,7 @@ is a callable that can provide timing information for the view pipeline: response.headers['X-View-Performance'] = '%.3f' % (end - start,) return wrapper_view - config.add_view_deriver(timing_view) + config.add_view_deriver(timing_view, 'timing view') View derivers are unique in that they have access to most of the options passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what @@ -1656,7 +1656,7 @@ token unless ``disable_csrf=True`` is passed to the view: require_csrf_view.options = ('disable_csrf',) - config.add_view_deriver(require_csrf_view) + config.add_view_deriver(require_csrf_view, 'require_csrf_view') def myview(request): return 'protected' -- cgit v1.2.3 From 35e632635b1b4e0a767024689d69d9469ae98c0f Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 14 Mar 2016 23:28:15 -0500 Subject: add a docstring for add_view_deriver and expose the method to the api docs --- docs/api/config.rst | 1 + docs/narr/hooks.rst | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/api/config.rst b/docs/api/config.rst index ae913d32c..e083dbc68 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -66,6 +66,7 @@ .. automethod:: add_tween .. automethod:: add_route_predicate .. automethod:: add_view_predicate + .. automethod:: add_view_deriver .. automethod:: set_request_factory .. automethod:: set_root_factory .. automethod:: set_session_factory diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index e3843cfbd..a5a03ef95 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1580,6 +1580,10 @@ the user-defined :term:`view callable`: view pipeline interface to accept ``(context, request)`` from all previous view derivers. +``rendered_view`` + + Adapts the result of :term:`view callable` into a :term:`response` object. + ``decorated_view`` Wraps the view with the decorators from the ``decorator`` option. @@ -1615,8 +1619,10 @@ It is possible to define custom view derivers which will affect all views in an application. There are many uses for this but most will likely be centered around monitoring and security. In order to register a custom :term:`view deriver` you should create a callable that conforms to the -:class:`pyramid.interfaces.IViewDeriver` interface. For example, below -is a callable that can provide timing information for the view pipeline: +:class:`pyramid.interfaces.IViewDeriver` interface and then register it with +your application using :meth:`pyramid.config.Configurator.add_view_deriver`. +For example, below is a callable that can provide timing information for the +view pipeline: .. code-block:: python :linenos: @@ -1676,7 +1682,7 @@ Ordering View Derivers ~~~~~~~~~~~~~~~~~~~~~~ By default, every new view deriver is added between the ``decorated_view`` -and ``mapped_view`` built-in derivers. It is possible to customize this +and ``rendered_view`` built-in derivers. It is possible to customize this ordering using the ``over`` and ``under`` options. Each option can use the names of other view derivers in order to specify an ordering. There should rarely be a reason to worry about the ordering of the derivers. -- cgit v1.2.3 From a116948ffe14449ac6ef29145b62eb2976130d83 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 17 Mar 2016 01:24:21 -0500 Subject: fix deriver docs to explain ordering issues --- docs/narr/hooks.rst | 81 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index a5a03ef95..4a1233244 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1556,6 +1556,8 @@ for a particular event type registration. View Derivers ------------- +.. versionadded:: 1.7 + Every URL processed by :app:`Pyramid` is matched against a custom view pipeline. See :ref:`router_chapter` for how this works. The view pipeline itself is built from the user-supplied :term:`view callable` which is then @@ -1565,28 +1567,33 @@ added functionality. View derivers are very similar to the ``decorator`` argument to :meth:`pyramid.config.Configurator.add_view` except that they have the option to execute for every view in the application. +It is helpful to think of a :term:`view deriver` as middleware for views. +Unlike tweens or WSGI middleware which are scoped to the application itself, +a view deriver is invoked once per view in the application and can use +configuration options from the view to customize its behavior. + Built-in View Derivers ~~~~~~~~~~~~~~~~~~~~~~ There are several builtin view derivers that :app:`Pyramid` will automatically -apply to any view. They are defined in order from closest to furthest from +apply to any view. Below they are defined in order from furthest to closest to the user-defined :term:`view callable`: -``mapped_view`` +``authdebug_view`` - Applies the :term:`view mapper` defined by the ``mapper`` option or the - application's default view mapper to the :term:`view callable`. This - is always the closest deriver to the user-defined view and standardizes the - view pipeline interface to accept ``(context, request)`` from all previous - view derivers. + Used to output useful debugging information when + ``pyramid.debug_authorization`` is enabled. This element is a noop otherwise. -``rendered_view`` +``secured_view`` - Adapts the result of :term:`view callable` into a :term:`response` object. + Enforce the ``permission`` defined on the view. This element is a noop if + no permission is defined. Note there will always be a permission defined + if a default permission was assigned via + :meth:`pyramid.config.Configurator.set_default_permission`. -``decorated_view`` +``owrapped_view`` - Wraps the view with the decorators from the ``decorator`` option. + Invokes the wrapped view defined by the ``wrapper`` option. ``http_cached_view`` @@ -1594,27 +1601,26 @@ the user-defined :term:`view callable`: option. This element is a noop if the ``pyramid.prevent_http_cache`` setting is enabled or the ``http_cache`` option is ``None``. -``owrapped_view`` +``decorated_view`` - Invokes the wrapped view defined by the ``wrapper`` option. + Wraps the view with the decorators from the ``decorator`` option. -``secured_view`` +``rendered_view`` - Enforce the ``permission`` defined on the view. This element is a noop if - no permission is defined. Note there will always be a permission defined - if a default permission was assigned via - :meth:`pyramid.config.Configurator.set_default_permission`. + Adapts the result of the :term:`view callable` into a :term:`response` + object. Below this point the result may be any Python object. -``authdebug_view`` +``mapped_view`` - Used to output useful debugging information when - ``pyramid.debug_authorization`` is enabled. This element is a noop otherwise. + Applies the :term:`view mapper` defined by the ``mapper`` option or the + application's default view mapper to the :term:`view callable`. This + is always the closest deriver to the user-defined view and standardizes the + view pipeline interface to accept ``(context, request)`` from all previous + view derivers. Custom View Derivers ~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 1.7 - It is possible to define custom view derivers which will affect all views in an application. There are many uses for this but most will likely be centered around monitoring and security. In order to register a custom @@ -1649,6 +1655,7 @@ token unless ``disable_csrf=True`` is passed to the view: .. code-block:: python :linenos: + from pyramid.response import Response from pyramid.session import check_csrf_token def require_csrf_view(view, info): @@ -1664,14 +1671,14 @@ token unless ``disable_csrf=True`` is passed to the view: config.add_view_deriver(require_csrf_view, 'require_csrf_view') - def myview(request): - return 'protected' + def protected_view(request): + return Response('protected') - def my_unprotected_view(request): - return 'unprotected' + def unprotected_view(request): + return Response('unprotected') - config.add_view(myview, name='safe', renderer='string') - config.add_view(my_unprotected_, name='unsafe', disable_csrf=True, renderer='string') + config.add_view(protected_view, name='safe') + config.add_view(unprotected_view, name='unsafe', disable_csrf=True) Navigating to ``/safe`` with a POST request will then fail when the call to :func:`pyramid.session.check_csrf_token` raises a @@ -1685,11 +1692,23 @@ By default, every new view deriver is added between the ``decorated_view`` and ``rendered_view`` built-in derivers. It is possible to customize this ordering using the ``over`` and ``under`` options. Each option can use the names of other view derivers in order to specify an ordering. There should -rarely be a reason to worry about the ordering of the derivers. +rarely be a reason to worry about the ordering of the derivers. Both ``over`` +and ``under`` may also be iterables of constraints. For either option, if one +or more constraints was defined, at least one must be satisfied or a +:class:`pyramid.exceptions.ConfigurationError` will be raised. This may be +used to define fallback constraints if another deriver is missing. -It is not possible to add a deriver OVER the ``mapped_view`` as the +It is not possible to add a view deriver under the ``mapped_view`` as the :term:`view mapper` is intimately tied to the signature of the user-defined :term:`view callable`. If you simply need to know what the original view callable was, it can be found as ``info.original_view`` on the provided :class:`pyramid.interfaces.IViewDeriverInfo` object passed to every view deriver. + +.. warning:: + + Any view derivers defined ``under`` the ``rendered_view`` are not + guaranteed to receive a valid response object. Rather they will receive the + result from the :term:`view mapper` which is likely the original response + returned from the view. This is possibly a dictionary for a renderer but it + may be any Python object that may be adapted into a response. -- cgit v1.2.3 From 6fb44f451abb657716ae0066ed70af66060ef3b8 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 21 Mar 2016 04:32:21 -0700 Subject: polish view derivers docs, minor grammar --- docs/narr/hooks.rst | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 4a1233244..a32e94d1a 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1548,6 +1548,7 @@ predicate author to make every predicate make sense for every event type; it is the responsibility of the predicate consumer to use predicates that make sense for a particular event type registration. + .. index:: single: view derivers @@ -1560,35 +1561,36 @@ View Derivers Every URL processed by :app:`Pyramid` is matched against a custom view pipeline. See :ref:`router_chapter` for how this works. The view pipeline -itself is built from the user-supplied :term:`view callable` which is then +itself is built from the user-supplied :term:`view callable`, which is then composed with :term:`view derivers `. A view deriver is a composable element of the view pipeline which is used to wrap a view with added functionality. View derivers are very similar to the ``decorator`` -argument to :meth:`pyramid.config.Configurator.add_view` except that they have +argument to :meth:`pyramid.config.Configurator.add_view`, except that they have the option to execute for every view in the application. It is helpful to think of a :term:`view deriver` as middleware for views. Unlike tweens or WSGI middleware which are scoped to the application itself, -a view deriver is invoked once per view in the application and can use +a view deriver is invoked once per view in the application, and can use configuration options from the view to customize its behavior. Built-in View Derivers ~~~~~~~~~~~~~~~~~~~~~~ -There are several builtin view derivers that :app:`Pyramid` will automatically +There are several built-in view derivers that :app:`Pyramid` will automatically apply to any view. Below they are defined in order from furthest to closest to the user-defined :term:`view callable`: ``authdebug_view`` Used to output useful debugging information when - ``pyramid.debug_authorization`` is enabled. This element is a noop otherwise. + ``pyramid.debug_authorization`` is enabled. This element is a no-op + otherwise. ``secured_view`` - Enforce the ``permission`` defined on the view. This element is a noop if - no permission is defined. Note there will always be a permission defined - if a default permission was assigned via + Enforce the ``permission`` defined on the view. This element is a no-op if no + permission is defined. Note there will always be a permission defined if a + default permission was assigned via :meth:`pyramid.config.Configurator.set_default_permission`. ``owrapped_view`` @@ -1598,7 +1600,7 @@ the user-defined :term:`view callable`: ``http_cached_view`` Applies cache control headers to the response defined by the ``http_cache`` - option. This element is a noop if the ``pyramid.prevent_http_cache`` setting + option. This element is a no-op if the ``pyramid.prevent_http_cache`` setting is enabled or the ``http_cache`` option is ``None``. ``decorated_view`` @@ -1621,11 +1623,11 @@ the user-defined :term:`view callable`: Custom View Derivers ~~~~~~~~~~~~~~~~~~~~ -It is possible to define custom view derivers which will affect all views in -an application. There are many uses for this but most will likely be centered -around monitoring and security. In order to register a custom -:term:`view deriver` you should create a callable that conforms to the -:class:`pyramid.interfaces.IViewDeriver` interface and then register it with +It is possible to define custom view derivers which will affect all views in an +application. There are many uses for this, but most will likely be centered +around monitoring and security. In order to register a custom :term:`view +deriver`, you should create a callable that conforms to the +:class:`pyramid.interfaces.IViewDeriver` interface, and then register it with your application using :meth:`pyramid.config.Configurator.add_view_deriver`. For example, below is a callable that can provide timing information for the view pipeline: @@ -1647,7 +1649,7 @@ view pipeline: View derivers are unique in that they have access to most of the options passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what -to do and they have a chance to affect every view in the application. +to do, and they have a chance to affect every view in the application. Let's look at one more example which will protect views by requiring a CSRF token unless ``disable_csrf=True`` is passed to the view: @@ -1688,15 +1690,16 @@ not error. Ordering View Derivers ~~~~~~~~~~~~~~~~~~~~~~ -By default, every new view deriver is added between the ``decorated_view`` -and ``rendered_view`` built-in derivers. It is possible to customize this -ordering using the ``over`` and ``under`` options. Each option can use the -names of other view derivers in order to specify an ordering. There should -rarely be a reason to worry about the ordering of the derivers. Both ``over`` -and ``under`` may also be iterables of constraints. For either option, if one -or more constraints was defined, at least one must be satisfied or a -:class:`pyramid.exceptions.ConfigurationError` will be raised. This may be -used to define fallback constraints if another deriver is missing. +By default, every new view deriver is added between the ``decorated_view`` and +``rendered_view`` built-in derivers. It is possible to customize this ordering +using the ``over`` and ``under`` options. Each option can use the names of +other view derivers in order to specify an ordering. There should rarely be a +reason to worry about the ordering of the derivers. + +Both ``over`` and ``under`` may also be iterables of constraints. For either +option, if one or more constraints was defined, at least one must be satisfied, +else a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may +be used to define fallback constraints if another deriver is missing. It is not possible to add a view deriver under the ``mapped_view`` as the :term:`view mapper` is intimately tied to the signature of the user-defined -- cgit v1.2.3 From 890ea8f7d57d680bd07e04bcab9a778d0f12f737 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 21 Mar 2016 04:34:43 -0700 Subject: polish view derivers docs, minor grammar --- docs/glossary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index 8928254f7..5e6aa145c 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -1097,5 +1097,5 @@ Glossary A view deriver is a composable component of the view pipeline which is used to create a :term:`view callable`. A view deriver is a callable implementing the :class:`pyramid.interfaces.IViewDeriver` interface. - Examples of builtin derivers including view mapper, the permission + Examples of built-in derivers including view mapper, the permission checker, and applying a renderer to a dictionary returned from the view. -- cgit v1.2.3 From 1514ea003dfe39fa79a0ec07bbbc14f239cb4eb2 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Mon, 7 Mar 2016 08:20:39 -0800 Subject: Pass vars to logging.config.fileConfig This allows one to set up a logging configuration that is parameterized based on variables specified on the command-line. e.g.: the application .ini file could have: ```ini [logger_root] level = %(LOGGING_LOGGER_ROOT_LEVEL)s handlers = console [handler_console] class = StreamHandler args = (sys.stderr,) level = %(LOGGING_HANDLER_CONSOLE_LEVEL)s formatter = generic ``` This app could be launched with: ``` pserve development.ini LOGGING_LOGGER_ROOT_LEVEL=DEBUG LOGGING_HANDLER_CONSOLE_LEVEL=DEBUG ``` --- docs/api/paster.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api/paster.rst b/docs/api/paster.rst index edc3738fc..27bc81a1f 100644 --- a/docs/api/paster.rst +++ b/docs/api/paster.rst @@ -11,4 +11,4 @@ .. autofunction:: get_appsettings(config_uri, name=None, options=None) - .. autofunction:: setup_logging(config_uri) + .. autofunction:: setup_logging(config_uri, global_conf=None) -- cgit v1.2.3 From a3db3cab713fecc0c83c742cfe3f0736b1d94a92 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 7 Apr 2016 01:16:45 -0500 Subject: separate the viewderiver module and allow overriding the mapper --- docs/api/viewderivers.rst | 16 ++++++++++++++++ docs/narr/hooks.rst | 9 +++------ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 docs/api/viewderivers.rst (limited to 'docs') diff --git a/docs/api/viewderivers.rst b/docs/api/viewderivers.rst new file mode 100644 index 000000000..a4ec107b6 --- /dev/null +++ b/docs/api/viewderivers.rst @@ -0,0 +1,16 @@ +.. _viewderivers_module: + +:mod:`pyramid.viewderivers` +--------------------------- + +.. automodule:: pyramid.viewderivers + + .. attribute:: INGRESS + + Constant representing the request ingress, for use in ``under`` + arguments to :meth:`pyramid.config.Configurator.add_view_deriver`. + + .. attribute:: MAPPED_VIEW + + Constant representing the closest view deriver, for use in ``over`` + arguments to :meth:`pyramid.config.Configurator.add_view_deriver`. diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index a32e94d1a..3a1ad8363 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1580,12 +1580,6 @@ There are several built-in view derivers that :app:`Pyramid` will automatically apply to any view. Below they are defined in order from furthest to closest to the user-defined :term:`view callable`: -``authdebug_view`` - - Used to output useful debugging information when - ``pyramid.debug_authorization`` is enabled. This element is a no-op - otherwise. - ``secured_view`` Enforce the ``permission`` defined on the view. This element is a no-op if no @@ -1593,6 +1587,9 @@ the user-defined :term:`view callable`: default permission was assigned via :meth:`pyramid.config.Configurator.set_default_permission`. + This element will also output useful debugging information when + ``pyramid.debug_authorization`` is enabled. + ``owrapped_view`` Invokes the wrapped view defined by the ``wrapper`` option. -- cgit v1.2.3 From c231d8174e811eec5a3faeafa5aee60757c6d31f Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 8 Apr 2016 00:47:01 -0500 Subject: update constraints for derivers as well as docs --- docs/api/viewderivers.rst | 7 ++++--- docs/narr/hooks.rst | 34 ++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'docs') diff --git a/docs/api/viewderivers.rst b/docs/api/viewderivers.rst index a4ec107b6..2a141501e 100644 --- a/docs/api/viewderivers.rst +++ b/docs/api/viewderivers.rst @@ -10,7 +10,8 @@ Constant representing the request ingress, for use in ``under`` arguments to :meth:`pyramid.config.Configurator.add_view_deriver`. - .. attribute:: MAPPED_VIEW + .. attribute:: VIEW - Constant representing the closest view deriver, for use in ``over`` - arguments to :meth:`pyramid.config.Configurator.add_view_deriver`. + Constant representing the :term:`view callable` at the end of the view + pipeline, for use in ``over`` arguments to + :meth:`pyramid.config.Configurator.add_view_deriver`. diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 3a1ad8363..2c3782387 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1617,6 +1617,14 @@ the user-defined :term:`view callable`: view pipeline interface to accept ``(context, request)`` from all previous view derivers. +.. warning:: + + Any view derivers defined ``under`` the ``rendered_view`` are not + guaranteed to receive a valid response object. Rather they will receive the + result from the :term:`view mapper` which is likely the original response + returned from the view. This is possibly a dictionary for a renderer but it + may be any Python object that may be adapted into a response. + Custom View Derivers ~~~~~~~~~~~~~~~~~~~~ @@ -1642,7 +1650,7 @@ view pipeline: response.headers['X-View-Performance'] = '%.3f' % (end - start,) return wrapper_view - config.add_view_deriver(timing_view, 'timing view') + config.add_view_deriver(timing_view) View derivers are unique in that they have access to most of the options passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what @@ -1668,7 +1676,7 @@ token unless ``disable_csrf=True`` is passed to the view: require_csrf_view.options = ('disable_csrf',) - config.add_view_deriver(require_csrf_view, 'require_csrf_view') + config.add_view_deriver(require_csrf_view) def protected_view(request): return Response('protected') @@ -1691,13 +1699,19 @@ By default, every new view deriver is added between the ``decorated_view`` and ``rendered_view`` built-in derivers. It is possible to customize this ordering using the ``over`` and ``under`` options. Each option can use the names of other view derivers in order to specify an ordering. There should rarely be a -reason to worry about the ordering of the derivers. +reason to worry about the ordering of the derivers except when the deriver +depends on other operations in the view pipeline. Both ``over`` and ``under`` may also be iterables of constraints. For either option, if one or more constraints was defined, at least one must be satisfied, else a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may be used to define fallback constraints if another deriver is missing. +Two sentinel values exist, :attr:`pyramid.viewderivers.INGRESS` and +:attr:`pyramid.viewderivers.VIEW`, which may be used when specifying +constraints at the edges of the view pipeline. For example, to add a deriver +at the start of the pipeline you may use ``under=INGRESS``. + It is not possible to add a view deriver under the ``mapped_view`` as the :term:`view mapper` is intimately tied to the signature of the user-defined :term:`view callable`. If you simply need to know what the original view @@ -1707,8 +1721,12 @@ deriver. .. warning:: - Any view derivers defined ``under`` the ``rendered_view`` are not - guaranteed to receive a valid response object. Rather they will receive the - result from the :term:`view mapper` which is likely the original response - returned from the view. This is possibly a dictionary for a renderer but it - may be any Python object that may be adapted into a response. + The default constraints for any view deriver are ``over='rendered_view'`` + and ``under='decorated_view'``. When escaping these constraints you must + take care to avoid cyclic dependencies between derivers. For example, if + you want to add a new view deriver before ``secured_view`` then + simply specifying ``over='secured_view'`` is not enough, because the + default is also under ``decorated view`` there will be an unsatisfiable + cycle. You must specify a valid ``under`` constraint as well, such as + ``under=INGRESS`` to fall between INGRESS and ``secured_view`` at the + beginning of the view pipeline. -- cgit v1.2.3 From 88c92b8f01ace15b57550cec2ab5c9127667f300 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 8 Apr 2016 02:18:51 -0700 Subject: Add pyramid_jinja2 example to i18n docs. Fixes #2437. --- docs/narr/i18n.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'docs') diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst index 839a48df4..b385eaf96 100644 --- a/docs/narr/i18n.rst +++ b/docs/narr/i18n.rst @@ -670,6 +670,21 @@ There exists a recipe within the :term:`Pyramid Community Cookbook` named :ref:`Mako Internationalization ` which explains how to add idiomatic i18n support to :term:`Mako` templates. + +.. index:: + single: Jinja2 i18n + +Jinja2 Pyramid i18n Support +--------------------------- + +The add-on `pyramid_jinja2 `_ +provides a scaffold with an example of how to use internationalization with +Jinja2 in Pyramid. See the documentation sections `Internalization (i18n) +`_ +and `Paster Template I18N +`_. + + .. index:: single: localization deployment settings single: default_locale_name -- cgit v1.2.3