summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2010-08-07 04:41:40 +0000
committerChris McDonough <chrism@agendaless.com>2010-08-07 04:41:40 +0000
commitab27bdb42d5b2c525466fe5570959f66b4814326 (patch)
treee845ef721f21e4b651cd5bfcd32564ff18525855
parenta48be71bca1caec1082061430f5787a0ebf7c249 (diff)
downloadpyramid-ab27bdb42d5b2c525466fe5570959f66b4814326.tar.gz
pyramid-ab27bdb42d5b2c525466fe5570959f66b4814326.tar.bz2
pyramid-ab27bdb42d5b2c525466fe5570959f66b4814326.zip
Features
-------- - There can only be one Not Found view in any ``repoze.bfg`` application. If you use ``repoze.bfg.view.append_slash_notfound_view`` as the Not Found view, it still must generate a NotFound response when it cannot redirect to a slash-appended URL; this not found response will be visible to site users. As of this release, if you wish to use a custom notfound view callable when ``append_slash_notfound_view`` does not redirect to a slash-appended URL, use a wrapper function as the ``repoze.bfg.exceptions.NotFound`` view; have this wrapper attach a view callable which returns a response to the request object named ``custom_notfound_view`` before calling ``append_slash_notfound_view``. For example:: from webob.exc import HTTPNotFound from repoze.bfg.exceptions import NotFound from repoze.bfg.view import append_slash_notfound_view def notfound_view(exc, request): def fallback_notfound_view(exc, request): return HTTPNotFound('It aint there, stop trying!') request.fallback_notfound_view = fallback_notfound_view return append_slash_notfound_view(exc, request) config.add_view(notfound_view, context=NotFound) ``custom_notfound_view`` must adhere to the two-argument view callable calling convention of ``(context, request)`` (``context`` will be the exception object). If ``custom_notfound_view`` is not found on the request object, a default notfound response will be generated when the ``append_slash_notfound_view`` doesn't redirect to a slash-appended URL. Documentation -------------- - Expanded the "Cleaning Up After a Request" section of the URL Dispatch narrative chapter. - Expanded the "Redirecting to Slash-Appended Routes" section of the URL Dispatch narrative chapter.
-rw-r--r--CHANGES.txt51
-rw-r--r--docs/narr/urldispatch.rst47
-rw-r--r--repoze/bfg/tests/test_view.py9
-rw-r--r--repoze/bfg/view.py44
4 files changed, 148 insertions, 3 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 1c62b25ff..65a08a781 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,54 @@
+Next release
+============
+
+Features
+--------
+
+- There can only be one Not Found view in any ``repoze.bfg``
+ application. If you use
+ ``repoze.bfg.view.append_slash_notfound_view`` as the Not Found
+ view, it still must generate a NotFound response when it cannot
+ redirect to a slash-appended URL; this not found response will be
+ visible to site users.
+
+ As of this release, if you wish to use a custom notfound view
+ callable when ``append_slash_notfound_view`` does not redirect to a
+ slash-appended URL, use a wrapper function as the
+ ``repoze.bfg.exceptions.NotFound`` view; have this wrapper attach a
+ view callable which returns a response to the request object named
+ ``custom_notfound_view`` before calling
+ ``append_slash_notfound_view``. For example::
+
+ from webob.exc import HTTPNotFound
+ from repoze.bfg.exceptions import NotFound
+ from repoze.bfg.view import append_slash_notfound_view
+
+ def notfound_view(exc, request):
+ def fallback_notfound_view(exc, request):
+ return HTTPNotFound('It aint there, stop trying!')
+ request.fallback_notfound_view = fallback_notfound_view
+ return append_slash_notfound_view(exc, request)
+
+ config.add_view(notfound_view, context=NotFound)
+
+ ``custom_notfound_view`` must adhere to the two-argument view
+ callable calling convention of ``(context, request)`` (``context``
+ will be the exception object).
+
+ If ``custom_notfound_view`` is not found on the request object, a
+ default notfound response will be generated when the
+ ``append_slash_notfound_view`` doesn't redirect to a slash-appended
+ URL.
+
+Documentation
+--------------
+
+- Expanded the "Cleaning Up After a Request" section of the URL
+ Dispatch narrative chapter.
+
+- Expanded the "Redirecting to Slash-Appended Routes" section of the
+ URL Dispatch narrative chapter.
+
1.3a7 (2010-08-01)
==================
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 916715bec..6e3a68c97 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -1058,6 +1058,8 @@ information.
.. index::
single: redirecting to slash-appended routes
+.. _redirecting_to_slash_appended_routes:
+
Redirecting to Slash-Appended Routes
------------------------------------
@@ -1114,12 +1116,24 @@ stanza:
view="repoze.bfg.view.append_slash_notfound_view"
/>
+Or use the :meth:`repoze.bfg.configuration.Configurator.add_view`
+method if you don't use ZCML:
+
+.. code-block:: python
+ :linenos:
+
+ from repoze.bfg.exceptions import NotFound
+ from repoze.bfg.view import append_slash_notfound_view
+ config.add_view(append_slash_notfound_view, context=NotFound)
+
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.
.. note:: This feature is new as of :mod:`repoze.bfg` 1.1.
+.. _cleaning_up_after_a_request:
+
Cleaning Up After a Request
---------------------------
@@ -1164,8 +1178,37 @@ Then in the ``configure.zcml`` of your package, inject the following:
<subscriber for="repoze.bfg.interfaces.INewRequest"
handler="mypackage.run.handle_teardown"/>
-This will cause the DBSession to be removed whenever the WSGI
-environment is destroyed (usually at the end of every request).
+Or, if you don't use ZCML, but you do use a :term:`scan` add a
+subscriber decorator:
+
+.. code-block:: python
+
+ from repoze.bfg.events import subscriber
+ from repoze.bfg.interfaces import INewRequest
+
+ @subscriber(INewRequest)
+ def handle_teardown(event):
+ environ = event.request.environ
+ environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
+
+Or finally, it can be done imperatively via the ``add_subscriber``
+method of a :term:`Configurator`.
+
+.. code-block:: python
+
+ from repoze.bfg.interfaces import INewRequest
+ from repoze.bfg.configuration imoport Configurator
+
+ def handle_teardown(event):
+ environ = event.request.environ
+ environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
+
+ config = Configurator()
+ config.add_subscriber(handle_teardown, INewRequest)
+
+Any of the above three ways to register a handle_teardown subscriber
+will cause the DBSession to be removed whenever the WSGI environment
+is destroyed (usually at the end of every request).
.. note:: This is only an example. In particular, it is not necessary
to cause ``DBSession.remove`` to be called as the result of an
diff --git a/repoze/bfg/tests/test_view.py b/repoze/bfg/tests/test_view.py
index bb178029c..27f468c74 100644
--- a/repoze/bfg/tests/test_view.py
+++ b/repoze/bfg/tests/test_view.py
@@ -429,6 +429,15 @@ class AppendSlashNotFoundView(BaseTest, unittest.TestCase):
response = self._callFUT(context, request)
self.assertEqual(response.status, '404 Not Found')
+ def test_custom_notfound_view(self):
+ request = self._makeRequest(PATH_INFO='/abc')
+ def notfound(exc, request):
+ return 'abc'
+ request.custom_notfound_view = notfound
+ context = Exception()
+ response = self._callFUT(context, request)
+ self.assertEqual(response, 'abc')
+
def test_no_path(self):
request = self._makeRequest()
context = Exception()
diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py
index 7a853eb28..30076b775 100644
--- a/repoze/bfg/view.py
+++ b/repoze/bfg/view.py
@@ -516,6 +516,46 @@ def append_slash_notfound_view(context, request):
.. note:: This function is new as of :mod:`repoze.bfg` version 1.1.
+ There can only be one Not Found view in any :mod:`repoze.bfg
+ application. If you use ``append_slash_notfound_view`` as the Not
+ Found view, it still must generate a NotFound response when it
+ cannot redirect to a slash-appended URL; this not found response
+ will be visible to site users.
+
+ If you wish to use a custom notfound view callable when
+ ``append_slash_notfound_view`` does not redirect to a
+ slash-appended URL, use a wrapper function as the
+ :exc:`repoze.bfg.exceptions.NotFound` view; have this wrapper
+ attach a :term:`view callable` which returns a response to the
+ request object named ``custom_notfound_view`` before calling
+ ``append_slash_notfound_view``. For example:
+
+ .. code-block:: python
+
+ from webob.exc import HTTPNotFound
+ from repoze.bfg.exceptions import NotFound
+ from repoze.bfg.view import append_slash_notfound_view
+
+ def notfound_view(exc, request):
+ def fallback_notfound_view(exc, request):
+ return HTTPNotFound('It aint there, stop trying!')
+ request.fallback_notfound_view = fallback_notfound_view
+ return append_slash_notfound_view(exc, request)
+
+ config.add_view(notfound_view, context=NotFound)
+
+ ``custom_notfound_view`` must adhere to the two-argument view
+ callable calling convention of ``(context, request)`` (``context``
+ will be the exception object).
+
+ If ``custom_notfound_view`` is not found on the request object, a
+ default notfound response will be generated when the
+ ``append_slash_notfound_view`` doesn't redirect to a
+ slash-appended URL.
+
+ .. note:: The checking for ``request.custom_notfound_view`` by
+ ``append_slash_notfound_view`` is new as of :mod:`repoze.bfg`
+ version 1.3.
"""
if not isinstance(context, Exception):
# backwards compat for an append_notslash_view registered via
@@ -529,5 +569,7 @@ def append_slash_notfound_view(context, request):
for route in mapper.get_routes():
if route.match(slashpath) is not None:
return HTTPFound(location=slashpath)
- return default_view(context, request, '404 Not Found')
+ notfound_view = getattr(request, 'custom_notfound_view',
+ default_notfound_view)
+ return notfound_view(context, request)