|
19 | 19 | from functools import update_wrapper
|
20 | 20 |
|
21 | 21 | from werkzeug.datastructures import ImmutableDict
|
22 |
| -from werkzeug.routing import Map, Rule, RequestRedirect |
| 22 | +from werkzeug.routing import Map, Rule, RequestRedirect, BuildError |
23 | 23 | from werkzeug.exceptions import HTTPException, InternalServerError, \
|
24 | 24 | MethodNotAllowed, BadRequest
|
25 | 25 |
|
@@ -341,16 +341,14 @@ def __init__(self, import_name, static_path=None, static_url_path=None,
|
341 | 341 | #: decorator.
|
342 | 342 | self.error_handler_spec = {None: self._error_handlers}
|
343 | 343 |
|
344 |
| - #: If not `None`, this function is called when :meth:`url_for` raises |
345 |
| - #: :exc:`~werkzeug.routing.BuildError`, with the call signature:: |
346 |
| - #: |
347 |
| - #: self.build_error_handler(error, endpoint, **values) |
348 |
| - #: |
349 |
| - #: Here, `error` is the instance of `BuildError`, and `endpoint` and |
350 |
| - #: `**values` are the arguments passed into :meth:`url_for`. |
| 344 | + #: A list of functions that are called when :meth:`url_for` raises a |
| 345 | + #: :exc:`~werkzeug.routing.BuildError`. Each function registered here |
| 346 | + #: is called with `error`, `endpoint` and `values`. If a function |
| 347 | + #: returns `None` or raises a `BuildError` the next function is |
| 348 | + #: tried. |
351 | 349 | #:
|
352 | 350 | #: .. versionadded:: 0.9
|
353 |
| - self.build_error_handler = None |
| 351 | + self.url_build_error_handlers = [] |
354 | 352 |
|
355 | 353 | #: A dictionary with lists of functions that should be called at the
|
356 | 354 | #: beginning of the request. The key of the dictionary is the name of
|
@@ -1490,19 +1488,24 @@ def inject_url_defaults(self, endpoint, values):
|
1490 | 1488 | for func in funcs:
|
1491 | 1489 | func(endpoint, values)
|
1492 | 1490 |
|
1493 |
| - def handle_build_error(self, error, endpoint, **values): |
| 1491 | + def handle_url_build_error(self, error, endpoint, values): |
1494 | 1492 | """Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
|
1495 |
| -
|
1496 |
| - Calls :attr:`build_error_handler` if it is not `None`. |
1497 | 1493 | """
|
1498 |
| - if self.build_error_handler is None: |
1499 |
| - exc_type, exc_value, tb = sys.exc_info() |
1500 |
| - if exc_value is error: |
1501 |
| - # exception is current, raise in context of original traceback. |
1502 |
| - raise exc_type, exc_value, tb |
1503 |
| - else: |
1504 |
| - raise error |
1505 |
| - return self.build_error_handler(error, endpoint, **values) |
| 1494 | + exc_type, exc_value, tb = sys.exc_info() |
| 1495 | + for handler in self.url_build_error_handlers: |
| 1496 | + try: |
| 1497 | + rv = handler(error, endpoint, values) |
| 1498 | + if rv is not None: |
| 1499 | + return rv |
| 1500 | + except BuildError, error: |
| 1501 | + pass |
| 1502 | + |
| 1503 | + # At this point we want to reraise the exception. If the error is |
| 1504 | + # still the same one we can reraise it with the original traceback, |
| 1505 | + # otherwise we raise it from here. |
| 1506 | + if error is exc_value: |
| 1507 | + raise exc_type, exc_value, tb |
| 1508 | + raise error |
1506 | 1509 |
|
1507 | 1510 | def preprocess_request(self):
|
1508 | 1511 | """Called before the actual request dispatching and will
|
|
0 commit comments