diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/api/config.rst | 12 | ||||
| -rw-r--r-- | docs/api/registry.rst | 7 | ||||
| -rw-r--r-- | docs/api/view.rst | 9 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 110 | ||||
| -rw-r--r-- | docs/narr/introspector.rst | 15 | ||||
| -rw-r--r-- | docs/narr/renderers.rst | 2 | ||||
| -rw-r--r-- | docs/narr/urldispatch.rst | 141 | ||||
| -rw-r--r-- | docs/tutorials/wiki/authorization.rst | 28 | ||||
| -rw-r--r-- | docs/tutorials/wiki/src/authorization/tutorial/views.py | 8 | ||||
| -rw-r--r-- | docs/tutorials/wiki/src/tests/tutorial/views.py | 8 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/authorization.rst | 26 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/src/authorization/tutorial/views.py | 8 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/src/tests/tutorial/views.py | 8 | ||||
| -rw-r--r-- | docs/whatsnew-1.3.rst | 80 |
14 files changed, 310 insertions, 152 deletions
diff --git a/docs/api/config.rst b/docs/api/config.rst index b76fed9cb..cd58e74d3 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -24,8 +24,8 @@ .. automethod:: add_route .. automethod:: add_static_view(name, path, cache_max_age=3600, permission=NO_PERMISSION_REQUIRED) .. automethod:: add_view - .. automethod:: set_forbidden_view - .. automethod:: set_notfound_view + .. automethod:: add_notfound_view + .. automethod:: add_forbidden_view :methodcategory:`Adding an Event Subscriber` @@ -76,18 +76,18 @@ .. automethod:: action .. automethod:: add_directive .. automethod:: with_package + .. automethod:: derive_view :methodcategory:`Utility Methods` .. automethod:: absolute_asset_spec - .. automethod:: derive_view .. automethod:: maybe_dotted - .. automethod:: setup_registry :methodcategory:`ZCA-Related APIs` .. automethod:: hook_zca .. automethod:: unhook_zca + .. automethod:: setup_registry :methodcategory:`Testing Helper APIs` @@ -112,9 +112,7 @@ The :term:`introspector` related to this configuration. It is an instance implementing the :class:`pyramid.interfaces.IIntrospector` - interface. If the Configurator constructor was supplied with an - ``introspector`` argument, this attribute will be that value. - Otherwise, it will be an instance of a default introspector type. + interface. .. note:: diff --git a/docs/api/registry.rst b/docs/api/registry.rst index e18d1b6c2..e62e2ba6f 100644 --- a/docs/api/registry.rst +++ b/docs/api/registry.rst @@ -38,10 +38,3 @@ This class is new as of :app:`Pyramid` 1.3. -.. class:: noop_introspector - - An introspector which throws away all registrations, useful for disabling - introspection altogether (pass as ``introspector`` to the - :term:`Configurator` constructor). - - This class is new as of :app:`Pyramid` 1.3. diff --git a/docs/api/view.rst b/docs/api/view.rst index 9f59ddae7..21d2bb90d 100644 --- a/docs/api/view.rst +++ b/docs/api/view.rst @@ -19,11 +19,14 @@ .. autoclass:: view_defaults :members: + .. autoclass:: notfound_view_config + :members: + + .. autoclass:: forbidden_view_config + :members: + .. autoclass:: static :members: :inherited-members: - .. autofunction:: append_slash_notfound_view(context, request) - - .. autoclass:: AppendSlashNotFoundViewFactory diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index eaccc14a3..b7f052b00 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -19,24 +19,66 @@ found view`, which is a :term:`view callable`. A default notfound view exists. The default not found view can be overridden through application configuration. -The :term:`not found view` callable is a view callable like any other. The -:term:`view configuration` which causes it to be a "not found" view consists -only of naming the :exc:`pyramid.httpexceptions.HTTPNotFound` class as the -``context`` of the view configuration. - If your application uses :term:`imperative configuration`, you can replace -the Not Found view by using the :meth:`pyramid.config.Configurator.add_view` -method to register an "exception view": +the Not Found view by using the +:meth:`pyramid.config.Configurator.add_notfound_view` method: .. code-block:: python :linenos: - from pyramid.httpexceptions import HTTPNotFound - from helloworld.views import notfound_view - config.add_view(notfound_view, context=HTTPNotFound) + from helloworld.views import notfound + config.add_notfound_view(notfound) + +Replace ``helloworld.views.notfound`` with a reference to the :term:`view +callable` you want to use to represent the Not Found view. The :term:`not +found view` callable is a view callable like any other. + +If your application instead uses :class:`pyramid.view.view_config` decorators +and a :term:`scan`, you can replace the Not Found view by using the +:class:`pyramid.view.notfound_view_config` decorator: + +.. code-block:: python + :linenos: + + from pyramid.view import notfound_view_config + + notfound_view_config() + def notfound(request): + return Response('Not Found, dude', status='404 Not Found') + + def main(globals, **settings): + config = Configurator() + config.scan() + +This does exactly what the imperative example above showed. + +Your application can define *multiple* not found views if necessary. Both +:meth:`pyramid.config.Configurator.add_notfound_view` and +:class:`pyramid.view.notfound_view_config` take most of the same arguments as +:class:`pyramid.config.Configurator.add_view` and +:class:`pyramid.view.view_config`, respectively. This means that not found +views can carry predicates limiting their applicability. For example: + +.. code-block:: python + :linenos: + + from pyramid.view import notfound_view_config -Replace ``helloworld.views.notfound_view`` with a reference to the -:term:`view callable` you want to use to represent the Not Found view. + notfound_view_config(request_method='GET') + def notfound_get(request): + return Response('Not Found during GET, dude', status='404 Not Found') + + notfound_view_config(request_method='POST') + def notfound_post(request): + return Response('Not Found during POST, dude', status='404 Not Found') + + def main(globals, **settings): + config = Configurator() + config.scan() + +The ``notfound_get`` view will be called when a view could not be found and +the request method was ``GET``. The ``notfound_post`` view will be called +when a view could not be found and the request method was ``POST``. Like any other view, the notfound view must accept at least a ``request`` parameter, or both ``context`` and ``request``. The ``request`` is the @@ -45,6 +87,11 @@ used in the call signature) will be the instance of the :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the view to be called. +Both :meth:`pyramid.config.Configurator.add_notfound_view` and +:class:`pyramid.view.notfound_view_config` can be used to automatically +redirect requests to slash-appended routes. See +:ref:`redirecting_to_slash_appended_routes` for examples. + Here's some sample code that implements a minimal NotFound view callable: .. code-block:: python @@ -52,7 +99,7 @@ Here's some sample code that implements a minimal NotFound view callable: from pyramid.httpexceptions import HTTPNotFound - def notfound_view(request): + def notfound(request): return HTTPNotFound() .. note:: @@ -66,6 +113,14 @@ Here's some sample code that implements a minimal NotFound view callable: ``pyramid.debug_notfound`` environment setting is true than it is when it is false. +.. note:: + + Both :meth:`pyramid.config.Configurator.add_notfound_view` and + :class:`pyramid.view.notfound_view_config` are new as of Pyramid 1.3. + Older Pyramid documentation instructed users to use ``add_view`` instead, + with a ``context`` of ``HTTPNotFound``. This still works; the convenience + method and decorator are just wrappers around this functionality. + .. warning:: When a NotFound view callable accepts an argument list as @@ -90,23 +145,40 @@ the view which generates it can be overridden as necessary. The :term:`forbidden view` callable is a view callable like any other. The :term:`view configuration` which causes it to be a "forbidden" view consists -only of naming the :exc:`pyramid.httpexceptions.HTTPForbidden` class as the -``context`` of the view configuration. +of using the meth:`pyramid.config.Configurator.add_forbidden_view` API or the +:class:`pyramid.view.forbidden_view_config` decorator. -You can replace the forbidden view by using the -:meth:`pyramid.config.Configurator.add_view` method to register an "exception -view": +For example, you can add a forbidden view by using the +:meth:`pyramid.config.Configurator.add_forbidden_view` method to register a +forbidden view: .. code-block:: python :linenos: from helloworld.views import forbidden_view from pyramid.httpexceptions import HTTPForbidden - config.add_view(forbidden_view, context=HTTPForbidden) + config.add_forbidden_view(forbidden_view) Replace ``helloworld.views.forbidden_view`` with a reference to the Python :term:`view callable` you want to use to represent the Forbidden view. +If instead you prefer to use decorators and a :term:`scan`, you can use the +:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable +as a forbidden view: + +.. code-block:: python + :linenos: + + from pyramid.view import forbidden_view_config + + forbidden_view_config() + def forbidden(request): + return Response('forbidden') + + def main(globals, **settings): + config = Configurator() + config.scan() + Like any other view, the forbidden view must accept at least a ``request`` parameter, or both ``context`` and ``request``. The ``context`` (available as ``request.context`` if you're using the request-only view argument diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst index d465c47d9..74595cac8 100644 --- a/docs/narr/introspector.rst +++ b/docs/narr/introspector.rst @@ -576,17 +576,14 @@ relationships. It looks something like this: Disabling Introspection ----------------------- -You can disable Pyramid introspection by passing the object -:attr:`pyramid.registry.noop_introspector` to the :term:`Configurator` -constructor in your application setup: +You can disable Pyramid introspection by passing the flag +``introspection=False`` to the :term:`Configurator` constructor in your +application setup: .. code-block:: python from pyramid.config import Configurator - from pyramid.registry import noop_introspector - config = Configurator(..., introspector=noop_introspector) + config = Configurator(..., introspection=False) -When the noop introspector is active, all introspectables generated by -configuration directives are thrown away. A noop introspector behaves just -like a "real" introspector, but the methods of a noop introspector do nothing -and return null values. +When ``introspection`` is ``False``, all introspectables generated by +configuration directives are thrown away. diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 1f1b1943b..76035cbdf 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -103,7 +103,7 @@ Likewise for an :term:`HTTP exception` response: .. code-block:: python :linenos: - from pyramid.httpexceptions import HTTPNotFound + from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config @view_config(renderer='json') diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index a7bf74786..7c0b437c1 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -772,95 +772,102 @@ ignored when ``static`` is ``True``. Redirecting to Slash-Appended Routes ------------------------------------ -For behavior like Django's ``APPEND_SLASH=True``, use the -:func:`~pyramid.view.append_slash_notfound_view` view as the :term:`Not Found -view` in your application. Defining this view as the :term:`Not Found view` -is a way to automatically redirect requests where the URL lacks a trailing -slash, but requires one to match the proper route. When configured, along -with at least one other route in your application, this view will be invoked -if the value of ``PATH_INFO`` does not already end in a slash, and if the -value of ``PATH_INFO`` *plus* a slash matches any route's pattern. In this -case it does an HTTP redirect to the slash-appended ``PATH_INFO``. - -Let's use an example, because this behavior is a bit magical. If the -``append_slash_notfound_view`` is configured in your application and your -route configuration looks like so: +For behavior like Django's ``APPEND_SLASH=True``, use the ``append_slash`` +argument to :meth:`pyramid.config.Configurator.add_notfound_view` or the +equivalent ``append_slash`` argument to the +:class:`pyramid.view.notfound_view_config` decorator. + +Adding ``append_slash=True`` is a way to automatically redirect requests +where the URL lacks a trailing slash, but requires one to match the proper +route. When configured, along with at least one other route in your +application, this view will be invoked if the value of ``PATH_INFO`` does not +already end in a slash, and if the value of ``PATH_INFO`` *plus* a slash +matches any route's pattern. In this case it does an HTTP redirect to the +slash-appended ``PATH_INFO``. + +To configure the slash-appending not found view in your application, change +the application's startup configuration, adding the following stanza: .. code-block:: python :linenos: - config.add_route('noslash', 'no_slash') - config.add_route('hasslash', 'has_slash/') +Let's use an example. If the following routes are configured in your +application: + +.. code-block:: python + :linenos: + + from pyramid.httpexceptions import HTTPNotFound + + def notfound(request): + return HTTPNotFound('Not found, bro.') + + def no_slash(request): + return Response('No slash') - config.add_view('myproject.views.no_slash', route_name='noslash') - config.add_view('myproject.views.has_slash', route_name='hasslash') + def has_slash(request): + return Response('Has slash') + + def main(g, **settings): + config = Configurator() + config.add_route('noslash', 'no_slash') + config.add_route('hasslash', 'has_slash/') + config.add_view(no_slash, route_name='noslash') + config.add_view(has_slash, route_name='hasslash') + config.add_notfound_view(notfound, append_slash=True) + +If a request enters the application with the ``PATH_INFO`` value of +``/no_slash``, the first route will match and the browser will show "No +slash". However, if a request enters the application with the ``PATH_INFO`` +value of ``/no_slash/``, *no* route will match, and the slash-appending not +found view will not find a matching route with an appended slash. As a +result, the ``notfound`` view will be called and it will return a "Not found, +bro." body. If a request enters the application with the ``PATH_INFO`` value of ``/has_slash/``, the second route will match. If a request enters the application with the ``PATH_INFO`` value of ``/has_slash``, a route *will* be found by the slash-appending not found view. An HTTP redirect to -``/has_slash/`` will be returned to the user's browser. +``/has_slash/`` will be returned to the user's browser. As a result, the +``notfound`` view will never actually be called. -If a request enters the application with the ``PATH_INFO`` value of -``/no_slash``, the first route will match. However, if a request enters the -application with the ``PATH_INFO`` value of ``/no_slash/``, *no* route will -match, and the slash-appending not found view will *not* find a matching -route with an appended slash. - -.. warning:: - - You **should not** rely on this mechanism to redirect ``POST`` requests. - The redirect of the slash-appending not found view will turn a ``POST`` - request into a ``GET``, losing any ``POST`` data in the original - request. - -To configure the slash-appending not found view in your application, change -the application's startup configuration, adding the following stanza: +The following application uses the :class:`pyramid.view.notfound_view_config` +and :class:`pyramid.view.view_config` decorators and a :term:`scan` to do +exactly the same job: .. code-block:: python :linenos: - config.add_view('pyramid.view.append_slash_notfound_view', - context='pyramid.httpexceptions.HTTPNotFound') - -See :ref:`view_module` and :ref:`changing_the_notfound_view` for more -information about the slash-appending not found view and for a more general -description of how to configure a not found view. + from pyramid.httpexceptions import HTTPNotFound + from pyramid.view import notfound_view_config, view_config -Custom Not Found View With Slash Appended Routes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + @notfound_view_config(append_slash=True) + def notfound(request): + return HTTPNotFound('Not found, bro.') -There can only be one :term:`Not Found view` in any :app:`Pyramid` -application. Even if you use :func:`~pyramid.view.append_slash_notfound_view` -as the Not Found view, :app:`Pyramid` still must generate a ``404 Not Found`` -response when it cannot redirect to a slash-appended URL; this not found -response will be visible to site users. + @view_config(route_name='noslash') + def no_slash(request): + return Response('No slash') -If you don't care what this 404 response looks like, and only you need -redirections to slash-appended route URLs, you may use the -:func:`~pyramid.view.append_slash_notfound_view` object as the Not Found view -as described above. However, if you wish to use a *custom* notfound view -callable when a URL cannot be redirected to a slash-appended URL, you may -wish to use an instance of the -:class:`~pyramid.view.AppendSlashNotFoundViewFactory` class as the Not Found -view, supplying a :term:`view callable` to be used as the custom notfound -view as the first argument to its constructor. For instance: + @view_config(route_name='hasslash') + def has_slash(request): + return Response('Has slash') -.. code-block:: python - :linenos: - - from pyramid.httpexceptions import HTTPNotFound - from pyramid.view import AppendSlashNotFoundViewFactory + def main(g, **settings): + config = Configurator() + config.add_route('noslash', 'no_slash') + config.add_route('hasslash', 'has_slash/') + config.scan() - def notfound_view(context, request): - return HTTPNotFound('It aint there, stop trying!') +.. warning:: - custom_append_slash = AppendSlashNotFoundViewFactory(notfound_view) - config.add_view(custom_append_slash, context=HTTPNotFound) + You **should not** rely on this mechanism to redirect ``POST`` requests. + The redirect of the slash-appending not found view will turn a ``POST`` + request into a ``GET``, losing any ``POST`` data in the original + request. -The ``notfound_view`` supplied must adhere to the two-argument view callable -calling convention of ``(context, request)`` (``context`` will be the -exception object). +See :ref:`view_module` and :ref:`changing_the_notfound_view` for for a more +general description of how to configure a view and/or a not found view. .. index:: pair: debugging; route matching diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index 8f583ece7..c1be2cc72 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -132,14 +132,14 @@ We'll add these views to the existing ``views.py`` file we have in our project. Here's what the ``login`` view callable will look like: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 83-111 + :lines: 86-113 :linenos: :language: python Here's what the ``logout`` view callable will look like: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 113-117 + :lines: 115-119 :linenos: :language: python @@ -149,18 +149,18 @@ different :term:`view configuration` for the ``login`` view callable. The first view configuration decorator configures the ``login`` view callable so it will be invoked when someone visits ``/login`` (when the context is a -Wiki and the view name is ``login``). The second decorator (with context of -``pyramid.httpexceptions.HTTPForbidden``) specifies a :term:`forbidden view`. -This configures our login view to be presented to the user when -:app:`Pyramid` detects that a view invocation can not be authorized. Because -we've configured a forbidden view, the ``login`` view callable will be -invoked whenever one of our users tries to execute a view callable that they -are not allowed to invoke as determined by the :term:`authorization policy` -in use. In our application, for example, this means that if a user has not -logged in, and he tries to add or edit a Wiki page, he will be shown the -login form. Before being allowed to continue on to the add or edit form, he -will have to provide credentials that give him permission to add or edit via -this login form. +Wiki and the view name is ``login``). The second decorator, named +``forbidden_view_config`` specifies a :term:`forbidden view`. This +configures our login view to be presented to the user when :app:`Pyramid` +detects that a view invocation can not be authorized. Because we've +configured a forbidden view, the ``login`` view callable will be invoked +whenever one of our users tries to execute a view callable that they are not +allowed to invoke as determined by the :term:`authorization policy` in use. +In our application, for example, this means that if a user has not logged in, +and he tries to add or edit a Wiki page, he will be shown the login form. +Before being allowed to continue on to the add or edit form, he will have to +provide credentials that give him permission to add or edit via this login +form. Note that we're relying on some additional imports within the bodies of these views (e.g. ``remember`` and ``forget``). We'll see a rendering of the diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py index 2f0502c17..fcbe6fe25 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py @@ -3,7 +3,10 @@ import re from pyramid.httpexceptions import HTTPFound -from pyramid.view import view_config +from pyramid.view import ( + view_config, + forbidden_view_config, + ) from pyramid.security import ( authenticated_userid, @@ -82,8 +85,7 @@ def edit_page(context, request): @view_config(context='.models.Wiki', name='login', renderer='templates/login.pt') -@view_config(context='pyramid.httpexceptions.HTTPForbidden', - renderer='templates/login.pt') +@forbidden_view_config(renderer='templates/login.pt') def login(request): login_url = request.resource_url(request.context, 'login') referrer = request.url diff --git a/docs/tutorials/wiki/src/tests/tutorial/views.py b/docs/tutorials/wiki/src/tests/tutorial/views.py index 2f0502c17..fcbe6fe25 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki/src/tests/tutorial/views.py @@ -3,7 +3,10 @@ import re from pyramid.httpexceptions import HTTPFound -from pyramid.view import view_config +from pyramid.view import ( + view_config, + forbidden_view_config, + ) from pyramid.security import ( authenticated_userid, @@ -82,8 +85,7 @@ def edit_page(context, request): @view_config(context='.models.Wiki', name='login', renderer='templates/login.pt') -@view_config(context='pyramid.httpexceptions.HTTPForbidden', - renderer='templates/login.pt') +@forbidden_view_config(renderer='templates/login.pt') def login(request): login_url = request.resource_url(request.context, 'login') referrer = request.url diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index b1d0bf37c..900bf0975 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -159,33 +159,35 @@ logged in user and redirect back to the front page. The ``login`` view callable will look something like this: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 87-113 + :lines: 89-115 :linenos: :language: python The ``logout`` view callable will look something like this: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 115-119 + :lines: 117-121 :linenos: :language: python -The ``login`` view callable is decorated with two ``@view_config`` -decorators, one which associates it with the ``login`` route, the other which -associates it with the ``HTTPForbidden`` context. The one which associates -it with the ``login`` route makes it visible when we visit ``/login``. The -one which associates it with the ``HTTPForbidden`` context makes it the -:term:`forbidden view`. The forbidden view is displayed whenever Pyramid or -your application raises an HTTPForbidden exception. In this case, we'll be -relying on the forbidden view to show the login form whenver someone attempts -to execute an action which they're not yet authorized to perform. +The ``login`` view callable is decorated with two decorators, a +``@view_config`` decorators, which associates it with the ``login`` route, +the other a ``@forbidden_view_config`` decorator which turns it in to an +:term:`exception view` when Pyramid raises a +:class:`pyramid.httpexceptions.HTTPForbidden` exception. The one which +associates it with the ``login`` route makes it visible when we visit +``/login``. The other one makes it a :term:`forbidden view`. The forbidden +view is displayed whenever Pyramid or your application raises an +HTTPForbidden exception. In this case, we'll be relying on the forbidden +view to show the login form whenver someone attempts to execute an action +which they're not yet authorized to perform. The ``logout`` view callable is decorated with a ``@view_config`` decorator which associates it with the ``logout`` route. This makes it visible when we visit ``/login``. We'll need to import some stuff to service the needs of these two functions: -the ``HTTPForbidden`` exception, a number of values from the +the ``pyramid.view.forbidden_view_config`` class, a number of values from the ``pyramid.security`` module, and a value from our newly added ``tutorial.security`` package. diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py index 087e6076b..1453cd2e6 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py @@ -4,10 +4,12 @@ from docutils.core import publish_parts from pyramid.httpexceptions import ( HTTPFound, HTTPNotFound, - HTTPForbidden, ) -from pyramid.view import view_config +from pyramid.view import ( + view_config, + forbidden_view_config, + ) from pyramid.security import ( remember, @@ -85,7 +87,7 @@ def edit_page(request): ) @view_config(route_name='login', renderer='templates/login.pt') -@view_config(context=HTTPForbidden, renderer='templates/login.pt') +@forbidden_view_config(renderer='templates/login.pt') def login(request): login_url = request.route_url('login') referrer = request.url diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py index 375f1f5a5..465d98ae1 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py @@ -4,10 +4,12 @@ from docutils.core import publish_parts from pyramid.httpexceptions import ( HTTPFound, HTTPNotFound, - HTTPForbidden, ) -from pyramid.view import view_config +from pyramid.view import ( + view_config, + forbidden_view_config, + ) from pyramid.security import ( remember, @@ -88,7 +90,7 @@ def edit_page(request): ) @view_config(route_name='login', renderer='templates/login.pt') -@view_config(context=HTTPForbidden, renderer='templates/login.pt') +@forbidden_view_config(renderer='templates/login.pt') def login(request): login_url = request.route_url('login') referrer = request.url diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst index d2df88093..101caed94 100644 --- a/docs/whatsnew-1.3.rst +++ b/docs/whatsnew-1.3.rst @@ -128,7 +128,6 @@ application developer. New APIs were added to support introspection :attr:`pyramid.registry.Introspectable`, -:attr:`pyramid.registry.noop_introspector`, :attr:`pyramid.config.Configurator.introspector`, :attr:`pyramid.config.Configurator.introspectable`, :attr:`pyramid.registry.Registry.introspector`. @@ -212,6 +211,38 @@ added, as well, but the configurator method should be preferred as it provides conflict detection and consistency in the lifetime of the properties. +Not Found and Forbidden View Helpers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Not Found helpers: + +- New API: :meth:`pyramid.config.Configurator.add_notfound_view`. This is a + wrapper for :meth:`pyramid.Config.configurator.add_view` which provides + support for an "append_slash" feature as well as doing the right thing when + it comes to permissions (a not found view should always be public). It + should be preferred over calling ``add_view`` directly with + ``context=HTTPNotFound`` as was previously recommended. + +- New API: :class:`pyramid.view.notfound_view_config``. This is a decorator + constructor like :class:`pyramid.view.view_config` that calls + :meth:`pyramid.config.Configurator.add_notfound_view` when scanned. It + should be preferred over using ``pyramid.view.view_config`` with + ``context=HTTPNotFound`` as was previously recommended. + +Forbidden helpers: + +- New API: :meth:`pyramid.config.Configurator.add_forbidden_view`. This is a + wrapper for :meth:`pyramid.Config.configurator.add_view` which does the + right thing about permissions. It should be preferred over calling + ``add_view`` directly with ``context=HTTPForbidden`` as was previously + recommended. + +- New API: :class:`pyramid.view.forbidden_view_config`. This is a decorator + constructor like :class:`pyramid.view.view_config` that calls + :meth:`pyramid.config.Configurator.add_forbidden_view` when scanned. It + should be preferred over using ``pyramid.view.view_config`` with + ``context=HTTPForbidden`` as was previously recommended. + Minor Feature Additions ----------------------- @@ -409,6 +440,38 @@ Backwards Incompatibilities ``pyramid.interfaces.IContextURL`` adapter is found when :meth:`pyramid.request.Request.resource_url` is called. +- Remove ``pyramid.config.Configurator.with_context`` class method. It was + never an API, it is only used by ``pyramid_zcml`` and its functionality has + been moved to that package's latest release. This means that you'll need + to use the 0.9.2 or later release of ``pyramid_zcml`` with this release of + Pyramid. + +- The older deprecated ``set_notfound_view`` Configurator method is now an + alias for the new ``add_notfound_view`` Configurator method. Likewise, the + older deprecated ``set_forbidden_view`` is now an alias for the new + ``add_forbidden_view`` Configurator method. This has the following impact: + the ``context`` sent to views with a ``(context, request)`` call signature + registered via the ``set_notfound_view`` or ``set_forbidden_view`` will now + be an exception object instead of the actual resource context found. Use + ``request.context`` to get the actual resource context. It's also + recommended to disuse ``set_notfound_view`` in favor of + ``add_notfound_view``, and disuse ``set_forbidden_view`` in favor of + ``add_forbidden_view`` despite the aliasing. + +Deprecations +------------ + +- The API documentation for ``pyramid.view.append_slash_notfound_view`` and + ``pyramid.view.AppendSlashNotFoundViewFactory`` was removed. These names + still exist and are still importable, but they are no longer APIs. Use + ``pyramid.config.Configurator.add_notfound_view(append_slash=True)`` or + ``pyramid.view.notfound_view_config(append_slash=True)`` to get the same + behavior. + +- The ``set_forbidden_view`` and ``set_notfound_view`` methods of the + Configurator were removed from the documentation. They have been + deprecated since Pyramid 1.1. + Documentation Enhancements -------------------------- @@ -441,6 +504,21 @@ Documentation Enhancements Rationale: it provides the correct info for the Python 2.5 version of GAE only, and this version of Pyramid does not support Python 2.5. +- Updated the :ref:`changing_the_forbidden_view` section, replacing + explanations of registering a view using ``add_view`` or ``view_config`` + with ones using ``add_forbidden_view`` or ``forbidden_view_config``. + +- Updated the :ref:`changing_the_notfound_view` section, replacing + explanations of registering a view using ``add_view`` or ``view_config`` + with ones using ``add_notfound_view`` or ``notfound_view_config``. + +- Updated the :ref:`redirecting_to_slash_appended_routes` section, replacing + explanations of registering a view using ``add_view`` or ``view_config`` + with ones using ``add_notfound_view`` or ``notfound_view_config`` + +- Updated all tutorials to use ``pyramid.view.forbidden_view_config`` rather + than ``pyramid.view.view_config`` with an HTTPForbidden context. + Dependency Changes ------------------ |
