summaryrefslogtreecommitdiff
path: root/repoze
diff options
context:
space:
mode:
Diffstat (limited to 'repoze')
-rw-r--r--repoze/bfg/request.py19
-rw-r--r--repoze/bfg/router.py30
-rw-r--r--repoze/bfg/tests/test_request.py4
-rw-r--r--repoze/bfg/tests/test_router.py27
4 files changed, 57 insertions, 23 deletions
diff --git a/repoze/bfg/request.py b/repoze/bfg/request.py
index 6e5417d9a..84a5660ef 100644
--- a/repoze/bfg/request.py
+++ b/repoze/bfg/request.py
@@ -40,6 +40,7 @@ class Request(WebobRequest):
implements(IRequest)
response_callbacks = ()
finished_callbacks = ()
+ exception = None
default_charset = 'utf-8'
def add_response_callback(self, callback):
@@ -72,7 +73,13 @@ class Request(WebobRequest):
Errors raised by callbacks are not handled specially. They
will be propagated to the caller of the :mod:`repoze.bfg`
- router application. """
+ router application.
+
+ .. note: ``add_response_callback`` is new in :mod:`repoze.bfg`
+ 1.3.
+
+ See also: :ref:`using_response_callbacks`.
+ """
callbacks = self.response_callbacks
if not callbacks:
@@ -101,7 +108,7 @@ class Request(WebobRequest):
def commit_callback(request):
'''commit or abort the transaction associated with request'''
- if hasattr(request, 'exception'):
+ if request.exception is not None:
transaction.abort()
else:
transaction.commit()
@@ -126,7 +133,13 @@ class Request(WebobRequest):
Errors raised by finished callbacks are not handled specially.
They will be propagated to the caller of the :mod:`repoze.bfg`
- router application. """
+ router application.
+
+ .. note: ``add_finished_callback`` is new in :mod:`repoze.bfg`
+ 1.3.
+
+ See also: :ref:`using_finished_callbacks`.
+ """
callbacks = self.finished_callbacks
if not callbacks:
diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py
index 6532beec4..e6de4fdd7 100644
--- a/repoze/bfg/router.py
+++ b/repoze/bfg/router.py
@@ -57,9 +57,9 @@ class Router(object):
has_listeners = registry.has_listeners
logger = self.logger
manager = self.threadlocal_manager
- threadlocals = {'registry':registry, 'request':None}
- manager.push(threadlocals)
request = None
+ threadlocals = {'registry':registry, 'request':request}
+ manager.push(threadlocals)
try:
# create the request
@@ -72,16 +72,19 @@ class Router(object):
request_iface = IRequest
try:
- # find the root
+ # find the root object
root_factory = self.root_factory
if self.routes_mapper is not None:
info = self.routes_mapper(request)
match, route = info['match'], info['route']
if route is not None:
- environ['wsgiorg.routing_args'] = ((), match)
- environ['bfg.routes.route'] = route
+ # TODO: kill off bfg.routes.* environ keys
+ # when traverser requires request arg, and
+ # cant cope with environ anymore (likely 1.4+)
+ environ['bfg.routes.route'] = route
environ['bfg.routes.matchdict'] = match
attrs['matchdict'] = match
+ attrs['matched_route'] = route
request_iface = registry.queryUtility(
IRouteRequest,
name=route.name,
@@ -91,7 +94,7 @@ class Router(object):
root = root_factory(request)
attrs['root'] = root
- # find a view callable
+ # find a context
traverser = adapters.queryAdapter(root, ITraverser)
if traverser is None:
traverser = ModelGraphTraverser(root)
@@ -102,6 +105,8 @@ class Router(object):
tdict['virtual_root_path'])
attrs.update(tdict)
has_listeners and registry.notify(ContextFound(request))
+
+ # find a view callable
context_iface = providedBy(context)
view_callable = adapters.lookup(
(IViewClassifier, request_iface, context_iface),
@@ -121,27 +126,31 @@ class Router(object):
logger and logger.debug(msg)
else:
msg = request.path_info
+ # repoze.bfg.message should die
environ['repoze.bfg.message'] = msg
raise NotFound(msg)
else:
response = view_callable(context, request)
- # handle exceptions raised during root finding and view lookup
+ # handle exceptions raised during root finding and view execution
except Exception, why:
+ attrs['exception'] = why
+
for_ = (IExceptionViewClassifier,
request_iface.combined,
providedBy(why))
view_callable = adapters.lookup(for_, IView, default=None)
+
if view_callable is None:
raise
- try:
+ # r.b.message should be deprecated
+ try:
msg = why[0]
- except Exception:
+ except:
msg = ''
environ['repoze.bfg.message'] = msg
- attrs['exception'] = why
response = view_callable(why, request)
# process the response
@@ -164,6 +173,7 @@ class Router(object):
return app_iter
finally:
+ # post-response cleanup
try:
if request is not None and request.finished_callbacks:
request._process_finished_callbacks()
diff --git a/repoze/bfg/tests/test_request.py b/repoze/bfg/tests/test_request.py
index d8a3c09fb..ae52f8420 100644
--- a/repoze/bfg/tests/test_request.py
+++ b/repoze/bfg/tests/test_request.py
@@ -23,6 +23,10 @@ class TestRequest(unittest.TestCase):
r = self._makeOne({'PATH_INFO':'/'})
self.assertEqual(r.charset, 'utf-8')
+ def test_exception_defaults_to_None(self):
+ r = self._makeOne({'PATH_INFO':'/'})
+ self.assertEqual(r.exception, None)
+
def test_params_decoded_from_utf_8_by_default(self):
environ = {
'PATH_INFO':'/',
diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py
index 199602a96..fade0679b 100644
--- a/repoze/bfg/tests/test_router.py
+++ b/repoze/bfg/tests/test_router.py
@@ -518,12 +518,11 @@ class TestRouter(unittest.TestCase):
self.assertEqual(request.subpath, [])
self.assertEqual(request.context, context)
self.assertEqual(request.root, root)
- routing_args = environ['wsgiorg.routing_args'][1]
- self.assertEqual(routing_args['action'], 'action1')
- self.assertEqual(routing_args['article'], 'article1')
- self.assertEqual(environ['bfg.routes.matchdict'], routing_args)
+ matchdict = {'action':'action1', 'article':'article1'}
+ self.assertEqual(environ['bfg.routes.matchdict'], matchdict)
self.assertEqual(environ['bfg.routes.route'].name, 'foo')
- self.assertEqual(request.matchdict, routing_args)
+ self.assertEqual(request.matchdict, matchdict)
+ self.assertEqual(request.matched_route.name, 'foo')
def test_call_route_matches_doesnt_overwrite_subscriber_iface(self):
from repoze.bfg.interfaces import INewRequest
@@ -559,12 +558,11 @@ class TestRouter(unittest.TestCase):
self.assertEqual(request.subpath, [])
self.assertEqual(request.context, context)
self.assertEqual(request.root, root)
- routing_args = environ['wsgiorg.routing_args'][1]
- self.assertEqual(routing_args['action'], 'action1')
- self.assertEqual(routing_args['article'], 'article1')
- self.assertEqual(environ['bfg.routes.matchdict'], routing_args)
+ matchdict = {'action':'action1', 'article':'article1'}
+ self.assertEqual(environ['bfg.routes.matchdict'], matchdict)
self.assertEqual(environ['bfg.routes.route'].name, 'foo')
- self.assertEqual(request.matchdict, routing_args)
+ self.assertEqual(request.matchdict, matchdict)
+ self.assertEqual(request.matched_route.name, 'foo')
self.failUnless(IFoo.providedBy(request))
def test_root_factory_raises_notfound(self):
@@ -634,6 +632,12 @@ class TestRouter(unittest.TestCase):
pass
from repoze.bfg.interfaces import IRequest
from repoze.bfg.interfaces import IViewClassifier
+ from repoze.bfg.interfaces import IRequestFactory
+ def rfactory(environ):
+ return request
+ self.registry.registerUtility(rfactory, IRequestFactory)
+ from repoze.bfg.request import Request
+ request = Request.blank('/')
context = DummyContext()
directlyProvides(context, IContext)
self._registerTraverserFactory(context, subpath=[''])
@@ -644,6 +648,9 @@ class TestRouter(unittest.TestCase):
router = self._makeOne()
start_response = DummyStartResponse()
self.assertRaises(RuntimeError, router, environ, start_response)
+ # ``exception`` must be attached to request even if a suitable
+ # exception view cannot be found
+ self.assertEqual(request.exception.__class__, RuntimeError)
def test_call_view_raises_exception_view(self):
from repoze.bfg.interfaces import IViewClassifier