summaryrefslogtreecommitdiff
path: root/docs/narr
diff options
context:
space:
mode:
authorcewing <cris@crisewing.com>2016-10-22 12:35:21 -0400
committercewing <cris@crisewing.com>2016-10-22 12:35:21 -0400
commit03f6d630364a9adf438e0bd7d7b9f3bc3175f093 (patch)
treede2aed9476c9d569375287a4ea89e9faf0f7b73a /docs/narr
parent1610c8fd3605f2ed481c37da27a1ce059419888a (diff)
parente73ae375581539ed42aa97d7cd6e96e6fbd64c79 (diff)
downloadpyramid-03f6d630364a9adf438e0bd7d7b9f3bc3175f093.tar.gz
pyramid-03f6d630364a9adf438e0bd7d7b9f3bc3175f093.tar.bz2
pyramid-03f6d630364a9adf438e0bd7d7b9f3bc3175f093.zip
Merge branch 'master' into issue.2614
Diffstat (limited to 'docs/narr')
-rw-r--r--docs/narr/commandline.rst31
-rw-r--r--docs/narr/firstapp.rst6
-rw-r--r--docs/narr/hooks.rst60
-rw-r--r--docs/narr/i18n.rst2
-rw-r--r--docs/narr/install.rst73
-rw-r--r--docs/narr/introduction.rst2
-rw-r--r--docs/narr/project.rst14
-rw-r--r--docs/narr/sessions.rst9
-rw-r--r--docs/narr/upgrading.rst6
-rw-r--r--docs/narr/urldispatch.rst8
-rw-r--r--docs/narr/viewconfig.rst19
-rw-r--r--docs/narr/views.rst40
12 files changed, 197 insertions, 73 deletions
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 6cd90d42f..242bc7ec7 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -649,6 +649,10 @@ using the :func:`pyramid.paster.bootstrap` command in the body of your script.
.. versionadded:: 1.1
:func:`pyramid.paster.bootstrap`
+.. versionchanged:: 1.8
+ Added the ability for ``bootstrap`` to cleanup automatically via the
+ ``with`` statement.
+
In the simplest case, :func:`pyramid.paster.bootstrap` can be used with a
single argument, which accepts the :term:`PasteDeploy` ``.ini`` file
representing your Pyramid application's configuration as a single argument:
@@ -656,8 +660,9 @@ representing your Pyramid application's configuration as a single argument:
.. code-block:: python
from pyramid.paster import bootstrap
- env = bootstrap('/path/to/my/development.ini')
- print(env['request'].route_url('home'))
+
+ with bootstrap('/path/to/my/development.ini') as env:
+ print(env['request'].route_url('home'))
:func:`pyramid.paster.bootstrap` returns a dictionary containing
framework-related information. This dictionary will always contain a
@@ -723,8 +728,9 @@ load instead of ``main``:
.. code-block:: python
from pyramid.paster import bootstrap
- env = bootstrap('/path/to/my/development.ini#another')
- print(env['request'].route_url('home'))
+
+ with bootstrap('/path/to/my/development.ini#another') as env:
+ print(env['request'].route_url('home'))
The above example specifies the ``another`` ``app``, ``pipeline``, or
``composite`` section of your PasteDeploy configuration file. The ``app``
@@ -761,9 +767,9 @@ desired request and passing it into :func:`~pyramid.paster.bootstrap`:
from pyramid.request import Request
request = Request.blank('/', base_url='https://example.com/prefix')
- env = bootstrap('/path/to/my/development.ini#another', request=request)
- print(env['request'].application_url)
- # will print 'https://example.com/prefix'
+ with bootstrap('/path/to/my/development.ini#another', request=request) as env:
+ print(env['request'].application_url)
+ # will print 'https://example.com/prefix'
Now you can readily use Pyramid's APIs for generating URLs:
@@ -776,7 +782,9 @@ Now you can readily use Pyramid's APIs for generating URLs:
Cleanup
~~~~~~~
-When your scripting logic finishes, it's good manners to call the ``closer``
+If you're using the ``with``-statement variant then there's nothing to
+worry about. However if you're using the returned environment directly then
+when your scripting logic finishes, it's good manners to call the ``closer``
callback:
.. code-block:: python
@@ -891,15 +899,12 @@ contains the following code:
omit = options.omit
if omit is None:
omit = []
- env = bootstrap(config_uri)
- settings, closer = env['registry'].settings, env['closer']
- try:
+ with bootstrap(config_uri) as env:
+ settings = env['registry'].settings
for k, v in settings.items():
if any([k.startswith(x) for x in omit]):
continue
print('%-40s %-20s' % (k, v))
- finally:
- closer()
This script uses the Python ``optparse`` module to allow us to make sense out
of extra arguments passed to the script. It uses the
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index a8491eabd..ad05976c0 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -27,15 +27,15 @@ installed, an HTTP server is started on TCP port 8080.
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/python helloworld.py
On Windows:
-.. code-block:: text
+.. code-block:: doscon
- C:\> %VENV%\Scripts\python.exe helloworld.py
+ c:\> %VENV%\Scripts\python helloworld.py
This command will not return and nothing will be printed to the console. When
port 8080 is visited by a browser on the URL ``/hello/world``, the server will
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 49ef29d3f..b22b31bf9 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -26,7 +26,7 @@ Not Found View by using the
:linenos:
def notfound(request):
- return Response('Not Found, dude', status='404 Not Found')
+ return Response('Not Found', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
@@ -45,7 +45,7 @@ and a :term:`scan`, you can replace the Not Found View by using the
@notfound_view_config()
def notfound(request):
- return Response('Not Found, dude', status='404 Not Found')
+ return Response('Not Found', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
@@ -67,11 +67,11 @@ Views can carry predicates limiting their applicability. For example:
@notfound_view_config(request_method='GET')
def notfound_get(request):
- return Response('Not Found during GET, dude', status='404 Not Found')
+ return Response('Not Found during GET', 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')
+ return Response('Not Found during POST', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
@@ -1481,7 +1481,7 @@ method. For example:
phash = text
def __call__(self, context, request):
- return getattr(context, 'content_type', None) == self.val
+ return request.content_type == self.val
The constructor of a predicate factory takes two arguments: ``val`` and
``config``. The ``val`` argument will be the argument passed to
@@ -1500,13 +1500,28 @@ with the name and the value serialized. The result of ``phash`` is not seen in
output anywhere, it just informs the uniqueness constraints for view
configuration.
-The ``__call__`` method of a predicate factory must accept a resource
-(``context``) and a request, and must return ``True`` or ``False``. It is the
-"meat" of the predicate.
+The ``__call__`` method differs depending on whether the predicate is used as
+a :term:`view predicate` or a :term:`route predicate`:
-You can use the same predicate factory as both a view predicate and as a route
-predicate, but you'll need to call ``add_view_predicate`` and
-``add_route_predicate`` separately with the same factory.
+- When used as a route predicate, the ``__call__`` signature is
+ ``(info, request)``. The ``info`` object is a dictionary containing two
+ keys: ``match`` and ``route``. ``info['match']`` is the matchdict containing
+ the patterns matched in the route pattern. ``info['route']`` is the
+ :class:`pyramid.interfaces.IRoute` object for the current route.
+
+- When used as a view predicate, the ``__call__`` signature is
+ ``(context, request)``. The ``context`` is the result of :term:`traversal`
+ performed using either the route's :term:`root factory` or the app's
+ :term:`default root factory`.
+
+In both cases the ``__call__`` method is expected to return ``True`` or
+``False``.
+
+It is possible to use the same predicate factory as both a view predicate and
+as a route predicate, but they'll need to handle the ``info`` or ``context``
+argument specially (many predicates do not need this argument) and you'll need
+to call ``add_view_predicate`` and ``add_route_predicate`` separately with
+the same factory.
.. _subscriber_predicates:
@@ -1639,7 +1654,8 @@ the user-defined :term:`view callable`:
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`.
+ :meth:`pyramid.config.Configurator.set_default_permission` unless the
+ view is an :term:`exception view`.
This element will also output useful debugging information when
``pyramid.debug_authorization`` is enabled.
@@ -1649,7 +1665,8 @@ the user-defined :term:`view callable`:
Used to check the CSRF token provided in the request. This element is a
no-op if ``require_csrf`` view option is not ``True``. Note there will
always be a ``require_csrf`` option if a default value was assigned via
- :meth:`pyramid.config.Configurator.set_default_csrf_options`.
+ :meth:`pyramid.config.Configurator.set_default_csrf_options` unless
+ the view is an :term:`exception view`.
``owrapped_view``
@@ -1695,6 +1712,8 @@ 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`.
+The callable should accept the ``view`` to be wrapped and the ``info`` object
+which is an instance of :class:`pyramid.interfaces.IViewDeriverInfo`.
For example, below is a callable that can provide timing information for the
view pipeline:
@@ -1745,6 +1764,21 @@ 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.
+.. _exception_view_derivers:
+
+Exception Views and View Derivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A :term:`view deriver` has the opportunity to wrap any view, including
+an :term:`exception view`. In general this is fine, but certain view derivers
+may wish to avoid doing certain things when handling exceptions. For example,
+the ``csrf_view`` and ``secured_view`` built-in view derivers will not perform
+security checks on exception views unless explicitly told to do so.
+
+You can check for ``info.exception_only`` on the
+:class:`pyramid.interfaces.IViewDeriverInfo` object when wrapping the view
+to determine whether you are wrapping an exception view or a normal view.
+
Ordering View Derivers
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index 131832aae..3549b53a5 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -294,7 +294,7 @@ Lingua like so:
.. code-block:: doscon
- C> %VENV%\Scripts\pip install lingua
+ c:\> %VENV%\Scripts\pip install lingua
.. index::
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 7d96f4074..570cb2285 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -21,9 +21,8 @@ the following sections.
.. sidebar:: Python Versions
- As of this writing, :app:`Pyramid` has been tested under Python 2.7,
- Python 3.3, Python 3.4, Python 3.5, PyPy, and PyPy3. :app:`Pyramid` does
- not run under any version of Python before 2.7.
+ As of this writing, :app:`Pyramid` is tested against Python 2.7,
+ Python 3.4, Python 3.5, PyPy.
:app:`Pyramid` is known to run on all popular UNIX-like systems such as Linux,
Mac OS X, and FreeBSD, as well as on Windows platforms. It is also known to
@@ -92,8 +91,24 @@ If your Windows system doesn't have a Python interpreter, you'll need to
install it by downloading a Python 3.x-series interpreter executable from
`python.org's download section <https://www.python.org/downloads/>`_ (the files
labeled "Windows Installer"). Once you've downloaded it, double click on the
-executable and accept the defaults during the installation process. You may
-also need to download and install the Python for Windows extensions.
+executable, and select appropriate options during the installation process. To
+standardize this documentation, we used the GUI installer and selected the
+following options:
+
+- Screen 1: Install Python 3.x.x (32- or 64-bit)
+ - Check "Install launcher for all users (recommended)"
+ - Check "Add Python 3.x to PATH"
+ - Click "Customize installation"
+- Screen 2: Optional Features
+ - Check all options
+ - Click "Next"
+- Screen 3: Advanced Options
+ - Check all options
+ - Customize install location: "C:\\Python3x", where "x" is the minor
+ version of Python
+ - Click "Next"
+
+You might also need to download and install the Python for Windows extensions.
.. seealso:: See the official Python documentation :ref:`Using Python on
Windows <python:using-on-windows>` for full details.
@@ -104,14 +119,19 @@ also need to download and install the Python for Windows extensions.
directions. Make sure you get the proper 32- or 64-bit build and Python
version.
+.. seealso:: `Python launcher for Windows
+ <https://docs.python.org/3/using/windows.html#launcher>`_ provides a command
+ ``py`` that allows users to run any installed version of Python.
+
.. warning::
- After you install Python on Windows, you may need to add the ``C:\Python3x``
- directory to your environment's ``Path``, where ``x`` is the minor version
- of installed Python, in order to make it possible to invoke Python from a
- command prompt by typing ``python``. To do so, right click ``My Computer``,
- select ``Properties`` --> ``Advanced Tab`` --> ``Environment Variables`` and
- add that directory to the end of the ``Path`` environment variable.
+ After you install Python on Windows, you might need to add the
+ ``c:\Python3x`` directory to your environment's ``Path``, where ``x`` is the
+ minor version of installed Python, in order to make it possible to invoke
+ Python from a command prompt by typing ``python``. To do so, right click
+ ``My Computer``, select ``Properties`` --> ``Advanced Tab`` -->
+ ``Environment Variables``, and add that directory to the end of the ``Path``
+ environment variable.
.. seealso:: See `Configuring Python (on Windows)
<https://docs.python.org/3/using/windows.html#configuring-python>`_ for
@@ -171,6 +191,29 @@ After installing Python as described previously in :ref:`for-mac-os-x-users` or
$ $VENV/bin/pip install "pyramid==\ |release|\ "
+.. index::
+ single: $VENV/bin/pip vs. source bin/activate
+
+.. _venv-bin-pip-vs-source-bin-activate:
+
+.. note:: Why use ``$VENV/bin/pip`` instead of ``source bin/activate``, then
+ ``pip``?
+
+ ``$VENV/bin/pip`` clearly specifies that ``pip`` is run from within the
+ virtual environment and not at the system level.
+
+ ``activate`` drops turds into the user's shell environment, leaving them
+ vulnerable to executing commands in the wrong context. ``deactivate`` might
+ not correctly restore previous shell environment variables.
+
+ Although using ``source bin/activate``, then ``pip``, requires fewer key
+ strokes to issue commands once invoked, there are other things to consider.
+ Michael F. Lamb (datagrok) presents a summary in `Virtualenv's bin/activate
+ is Doing It Wrong <https://gist.github.com/datagrok/2199506>`_.
+
+ Ultimately we prefer to keep things clear and simple, so we use
+ ``$VENV/bin/pip``.
+
.. index::
single: installing on Windows
@@ -190,7 +233,8 @@ After installing Python as described previously in
c:\> set VENV=c:\env
# replace "x" with your minor version of Python 3
- c:\> c:\Python3x\Scripts\python3 -m venv %VENV%
+ c:\> c:\Python3x\python -m venv %VENV%
+ c:\> cd %VENV%
You can either follow the use of the environment variable ``%VENV%``, or
replace it with the root directory of the virtual environment. If you choose
@@ -204,7 +248,10 @@ After installing Python as described previously in
.. parsed-literal::
- c:\\env> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
+ c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
+
+.. note:: See the note above for :ref:`Why use $VENV/bin/pip instead of source
+ bin/activate, then pip <venv-bin-pip-vs-source-bin-activate>`.
What Gets Installed
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 112754b6a..40d9c14a8 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -821,7 +821,7 @@ Every release of Pyramid has 100% statement coverage via unit and integration
tests, as measured by the ``coverage`` tool available on PyPI. It also has
greater than 95% decision/condition coverage as measured by the
``instrumental`` tool available on PyPI. It is automatically tested by Travis,
-and Jenkins on Python 2.7, Python 3.3, Python 3.4, Python 3.5, PyPy, and PyPy3
+and Jenkins on Python 2.7, Python 3.4, Python 3.5, and PyPy
after each commit to its GitHub repository. Official Pyramid add-ons are held
to a similar testing standard. We still find bugs in Pyramid and its official
add-ons, but we've noticed we find a lot more of them while working on other
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 1ce12a938..71bd176f6 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -87,9 +87,9 @@ On UNIX:
Or on Windows:
-.. code-block:: text
+.. code-block:: doscon
- > %VENV%\Scripts\pcreate -s starter MyProject
+ c:\> %VENV%\Scripts\pcreate -s starter MyProject
As a result of invoking the ``pcreate`` command, a directory named
``MyProject`` is created. That directory is a :term:`project` directory. The
@@ -161,8 +161,8 @@ Or on Windows:
.. code-block:: doscon
- > cd MyProject
- > %VENV%\Scripts\pip install -e .
+ c:\> cd MyProject
+ c:\> %VENV%\Scripts\pip install -e .
Elided output from a run of this command on UNIX is shown below:
@@ -199,7 +199,7 @@ On Windows:
.. code-block:: doscon
- > %VENV%\Scripts\pip install -e ".[testing]"
+ c:\> %VENV%\Scripts\pip install -e ".[testing]"
Once the testing requirements are installed, then you can run the tests using
the ``py.test`` command that was just installed in the ``bin`` directory of
@@ -215,7 +215,7 @@ On Windows:
.. code-block:: doscon
- > %VENV%\Scripts\py.test -q
+ c:\> %VENV%\Scripts\py.test -q
Here's sample output from a test run on UNIX:
@@ -282,7 +282,7 @@ On Windows:
.. code-block:: text
- > %VENV%\Scripts\pserve development.ini
+ c:\> %VENV%\Scripts\pserve development.ini
Here's sample output from a run of ``pserve`` on UNIX:
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index a1319e45f..5b24201a9 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -157,6 +157,12 @@ The following session factories exist at the time of this writing.
======================= ======= =============================
Session Factory Backend Description
======================= ======= =============================
+pyramid_nacl_session_ PyNaCl_ Defines an encrypting,
+ pickle-based cookie
+ serializer, using PyNaCl to
+ generate the symmetric
+ encryption for the cookie
+ state.
pyramid_redis_sessions_ Redis_ Server-side session library
for Pyramid, using Redis for
storage.
@@ -165,6 +171,9 @@ pyramid_beaker_ Beaker_ Session factory for Pyramid
sessioning system.
======================= ======= =============================
+.. _pyramid_nacl_session: https://pypi.python.org/pypi/pyramid_nacl_session
+.. _PyNaCl: https://pynacl.readthedocs.io/en/latest/secret/
+
.. _pyramid_redis_sessions: https://pypi.python.org/pypi/pyramid_redis_sessions
.. _Redis: http://redis.io/
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index 21b696775..4e434c3c6 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -205,10 +205,10 @@ On UNIX, you can do that via:
On Windows, you need to issue two commands:
-.. code-block:: bash
+.. code-block:: doscon
- C:\> set PYTHONWARNINGS=default
- C:\> Scripts/pserve.exe development.ini
+ c:\> set PYTHONWARNINGS=default
+ c:\> Scripts/pserve.exe development.ini
At this point, it's ensured that deprecation warnings will be printed to the
console whenever a codepath is hit that generates one. You can then click
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 2472ace31..9ac01e24a 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -557,7 +557,7 @@ Here is an example of a corresponding ``mypackage.views`` module:
@view_config(route_name='idea')
def idea_view(request):
- return Response(request.matchdict['id'])
+ return Response(request.matchdict['idea'])
@view_config(route_name='user')
def user_view(request):
@@ -850,7 +850,7 @@ application:
from pyramid.httpexceptions import HTTPNotFound
def notfound(request):
- return HTTPNotFound('Not found, bro.')
+ return HTTPNotFound()
def no_slash(request):
return Response('No slash')
@@ -871,7 +871,7 @@ If a request enters the application with the ``PATH_INFO`` value of
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.
+``notfound`` view will be called and it will return a "Not found" 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
@@ -892,7 +892,7 @@ exactly the same job:
@notfound_view_config(append_slash=True)
def notfound(request):
- return HTTPNotFound('Not found, bro.')
+ return HTTPNotFound()
@view_config(route_name='noslash')
def no_slash(request):
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index cd5b8feb0..7cb8e0306 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -34,7 +34,7 @@ determine the set of circumstances which must be true for the view callable to
be invoked.
A view configuration statement is made about information present in the
-:term:`context` resource and the :term:`request`.
+:term:`context` resource (or exception) and the :term:`request`.
View configuration is performed in one of two ways:
@@ -306,9 +306,26 @@ configured view.
represented class or if the :term:`context` resource provides the represented
interface; it is otherwise false.
+ It is possible to pass an exception class as the context if your context may
+ subclass an exception. In this case *two* views will be registered. One
+ will match normal incoming requests, and the other will match as an
+ :term:`exception view` which only occurs when an exception is raised during
+ the normal request processing pipeline.
+
If ``context`` is not supplied, the value ``None``, which matches any
resource, is used.
+``exception_only``
+
+ When this value is ``True``, the ``context`` argument must be a subclass of
+ ``Exception``. This flag indicates that only an :term:`exception view` should
+ be created, and that this view should not match if the traversal
+ :term:`context` matches the ``context`` argument. If the ``context`` is a
+ subclass of ``Exception`` and this value is ``False`` (the default), then a
+ view will be registered to match the traversal :term:`context` as well.
+
+ .. versionadded:: 1.8
+
``route_name``
If ``route_name`` is supplied, the view callable will be invoked only when
the named route has matched.
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 770d27919..ab139ea19 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -262,10 +262,16 @@ specialized views as described in :ref:`special_exceptions_in_callables` can
also be used by application developers to convert arbitrary exceptions to
responses.
-To register a view that should be called whenever a particular exception is
-raised from within :app:`Pyramid` view code, use the exception class (or one of
-its superclasses) as the :term:`context` of a view configuration which points
-at a view callable for which you'd like to generate a response.
+To register an :term:`exception view` that should be called whenever a
+particular exception is raised from within :app:`Pyramid` view code, use
+:meth:`pyramid.config.Configurator.add_exception_view` to register a view
+configuration which matches the exception (or a subclass of the exception) and
+points at a view callable for which you'd like to generate a response. The
+exception will be passed as the ``context`` argument to any
+:term:`view predicate` registered with the view, as well as to the view itself.
+For convenience a new decorator exists,
+:class:`pyramid.views.exception_view_config`, which may be used to easily
+register exception views.
For example, given the following exception class in a module named
``helloworld.exceptions``:
@@ -277,17 +283,16 @@ For example, given the following exception class in a module named
def __init__(self, msg):
self.msg = msg
-
You can wire a view callable to be called whenever any of your *other* code
raises a ``helloworld.exceptions.ValidationFailure`` exception:
.. code-block:: python
:linenos:
- from pyramid.view import view_config
+ from pyramid.view import exception_view_config
from helloworld.exceptions import ValidationFailure
- @view_config(context=ValidationFailure)
+ @exception_view_config(ValidationFailure)
def failed_validation(exc, request):
response = Response('Failed validation: %s' % exc.msg)
response.status_int = 500
@@ -308,7 +313,7 @@ view registration:
from pyramid.view import view_config
from helloworld.exceptions import ValidationFailure
- @view_config(context=ValidationFailure, route_name='home')
+ @exception_view_config(ValidationFailure, route_name='home')
def failed_validation(exc, request):
response = Response('Failed validation: %s' % exc.msg)
response.status_int = 500
@@ -327,14 +332,21 @@ which have a name will be ignored.
.. note::
- Normal (i.e., non-exception) views registered against a context resource type
- which inherits from :exc:`Exception` will work normally. When an exception
- view configuration is processed, *two* views are registered. One as a
- "normal" view, the other as an "exception" view. This means that you can use
- an exception as ``context`` for a normal view.
+ In most cases, you should register an :term:`exception view` by using
+ :meth:`pyramid.config.Configurator.add_exception_view`. However, it is
+ possible to register "normal" (i.e., non-exception) views against a context
+ resource type which inherits from :exc:`Exception` (i.e.,
+ ``config.add_view(context=Exception)``). When the view configuration is
+ processed, *two* views are registered. One as a "normal" view, the other
+ as an :term:`exception view`. This means that you can use an exception as
+ ``context`` for a normal view.
+
+ The view derivers that wrap these two views may behave differently.
+ See :ref:`exception_view_derivers` for more information about this.
Exception views can be configured with any view registration mechanism:
-``@view_config`` decorator or imperative ``add_view`` styles.
+``@exception_view_config`` decorator or imperative ``add_exception_view``
+styles.
.. note::