forked from orbit-oss/flask
Improved interface for the URL build error handler
This commit is contained in:
parent
e78e2a1641
commit
2053d04db0
3 changed files with 29 additions and 25 deletions
43
flask/app.py
43
flask/app.py
|
|
@ -19,7 +19,7 @@ from itertools import chain
|
||||||
from functools import update_wrapper
|
from functools import update_wrapper
|
||||||
|
|
||||||
from werkzeug.datastructures import ImmutableDict
|
from werkzeug.datastructures import ImmutableDict
|
||||||
from werkzeug.routing import Map, Rule, RequestRedirect
|
from werkzeug.routing import Map, Rule, RequestRedirect, BuildError
|
||||||
from werkzeug.exceptions import HTTPException, InternalServerError, \
|
from werkzeug.exceptions import HTTPException, InternalServerError, \
|
||||||
MethodNotAllowed, BadRequest
|
MethodNotAllowed, BadRequest
|
||||||
|
|
||||||
|
|
@ -341,16 +341,14 @@ class Flask(_PackageBoundObject):
|
||||||
#: decorator.
|
#: decorator.
|
||||||
self.error_handler_spec = {None: self._error_handlers}
|
self.error_handler_spec = {None: self._error_handlers}
|
||||||
|
|
||||||
#: If not `None`, this function is called when :meth:`url_for` raises
|
#: A list of functions that are called when :meth:`url_for` raises a
|
||||||
#: :exc:`~werkzeug.routing.BuildError`, with the call signature::
|
#: :exc:`~werkzeug.routing.BuildError`. Each function registered here
|
||||||
#:
|
#: is called with `error`, `endpoint` and `values`. If a function
|
||||||
#: self.build_error_handler(error, endpoint, **values)
|
#: returns `None` or raises a `BuildError` the next function is
|
||||||
#:
|
#: tried.
|
||||||
#: Here, `error` is the instance of `BuildError`, and `endpoint` and
|
|
||||||
#: `**values` are the arguments passed into :meth:`url_for`.
|
|
||||||
#:
|
#:
|
||||||
#: .. versionadded:: 0.9
|
#: .. versionadded:: 0.9
|
||||||
self.build_error_handler = None
|
self.url_build_error_handlers = []
|
||||||
|
|
||||||
#: A dictionary with lists of functions that should be called at the
|
#: A dictionary with lists of functions that should be called at the
|
||||||
#: beginning of the request. The key of the dictionary is the name of
|
#: beginning of the request. The key of the dictionary is the name of
|
||||||
|
|
@ -1490,19 +1488,24 @@ class Flask(_PackageBoundObject):
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
func(endpoint, values)
|
func(endpoint, values)
|
||||||
|
|
||||||
def handle_build_error(self, error, endpoint, **values):
|
def handle_url_build_error(self, error, endpoint, values):
|
||||||
"""Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
|
"""Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
|
||||||
|
|
||||||
Calls :attr:`build_error_handler` if it is not `None`.
|
|
||||||
"""
|
"""
|
||||||
if self.build_error_handler is None:
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
exc_type, exc_value, tb = sys.exc_info()
|
for handler in self.url_build_error_handlers:
|
||||||
if exc_value is error:
|
try:
|
||||||
# exception is current, raise in context of original traceback.
|
rv = handler(error, endpoint, values)
|
||||||
raise exc_type, exc_value, tb
|
if rv is not None:
|
||||||
else:
|
return rv
|
||||||
raise error
|
except BuildError, error:
|
||||||
return self.build_error_handler(error, endpoint, **values)
|
pass
|
||||||
|
|
||||||
|
# At this point we want to reraise the exception. If the error is
|
||||||
|
# still the same one we can reraise it with the original traceback,
|
||||||
|
# otherwise we raise it from here.
|
||||||
|
if error is exc_value:
|
||||||
|
raise exc_type, exc_value, tb
|
||||||
|
raise error
|
||||||
|
|
||||||
def preprocess_request(self):
|
def preprocess_request(self):
|
||||||
"""Called before the actual request dispatching and will
|
"""Called before the actual request dispatching and will
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import imp
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import pkgutil
|
import pkgutil
|
||||||
|
|
@ -303,10 +302,12 @@ def url_for(endpoint, **values):
|
||||||
rv = url_adapter.build(endpoint, values, method=method,
|
rv = url_adapter.build(endpoint, values, method=method,
|
||||||
force_external=external)
|
force_external=external)
|
||||||
except BuildError, error:
|
except BuildError, error:
|
||||||
|
# We need to inject the values again so that the app callback can
|
||||||
|
# deal with that sort of stuff.
|
||||||
values['_external'] = external
|
values['_external'] = external
|
||||||
values['_anchor'] = anchor
|
values['_anchor'] = anchor
|
||||||
values['_method'] = method
|
values['_method'] = method
|
||||||
return appctx.app.handle_build_error(error, endpoint, **values)
|
return appctx.app.handle_url_build_error(error, endpoint, values)
|
||||||
|
|
||||||
rv = url_adapter.build(endpoint, values, method=method,
|
rv = url_adapter.build(endpoint, values, method=method,
|
||||||
force_external=external)
|
force_external=external)
|
||||||
|
|
|
||||||
|
|
@ -712,13 +712,13 @@ class BasicFunctionalityTestCase(FlaskTestCase):
|
||||||
try:
|
try:
|
||||||
raise RuntimeError('Test case where BuildError is not current.')
|
raise RuntimeError('Test case where BuildError is not current.')
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
self.assertRaises(BuildError, app.handle_build_error, error, 'spam')
|
self.assertRaises(BuildError, app.handle_url_build_error, error, 'spam', {})
|
||||||
|
|
||||||
# Test a custom handler.
|
# Test a custom handler.
|
||||||
def handler(error, endpoint, **values):
|
def handler(error, endpoint, values):
|
||||||
# Just a test.
|
# Just a test.
|
||||||
return '/test_handler/'
|
return '/test_handler/'
|
||||||
app.build_error_handler = handler
|
app.url_build_error_handlers.append(handler)
|
||||||
with app.test_request_context():
|
with app.test_request_context():
|
||||||
self.assert_equal(flask.url_for('spam'), '/test_handler/')
|
self.assert_equal(flask.url_for('spam'), '/test_handler/')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue