Merge pull request #1431 from untitaker/flask-errorhandling-amend
Some cleanup for errorhandling refactor
This commit is contained in:
commit
aaebe9fe25
2 changed files with 105 additions and 97 deletions
34
flask/app.py
34
flask/app.py
|
|
@ -14,7 +14,7 @@ from threading import Lock
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from functools import update_wrapper
|
from functools import update_wrapper
|
||||||
from collections import Mapping
|
from collections import Mapping, deque
|
||||||
|
|
||||||
from werkzeug.datastructures import ImmutableDict
|
from werkzeug.datastructures import ImmutableDict
|
||||||
from werkzeug.routing import Map, Rule, RequestRedirect, BuildError
|
from werkzeug.routing import Map, Rule, RequestRedirect, BuildError
|
||||||
|
|
@ -1412,26 +1412,36 @@ class Flask(_PackageBoundObject):
|
||||||
"""
|
"""
|
||||||
exc_class, code = self._get_exc_class_and_code(type(e))
|
exc_class, code = self._get_exc_class_and_code(type(e))
|
||||||
|
|
||||||
def find_superclass(handler_map):
|
def find_handler(handler_map):
|
||||||
if not handler_map:
|
if not handler_map:
|
||||||
return None
|
return
|
||||||
for superclass in exc_class.__mro__:
|
queue = deque(exc_class.__mro__)
|
||||||
if superclass is BaseException:
|
# Protect from geniuses who might create circular references in
|
||||||
return None
|
# __mro__
|
||||||
handler = handler_map.get(superclass)
|
done = set()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
cls = queue.popleft()
|
||||||
|
if cls in done:
|
||||||
|
continue
|
||||||
|
done.add(cls)
|
||||||
|
handler = handler_map.get(cls)
|
||||||
if handler is not None:
|
if handler is not None:
|
||||||
handler_map[exc_class] = handler # cache for next time exc_class is raised
|
# cache for next time exc_class is raised
|
||||||
|
handler_map[exc_class] = handler
|
||||||
return handler
|
return handler
|
||||||
return None
|
|
||||||
|
queue.extend(cls.__mro__)
|
||||||
|
|
||||||
# try blueprint handlers
|
# try blueprint handlers
|
||||||
handler = find_superclass(self.error_handler_spec.get(request.blueprint, {}).get(code))
|
handler = find_handler(self.error_handler_spec
|
||||||
|
.get(request.blueprint, {})
|
||||||
|
.get(code))
|
||||||
if handler is not None:
|
if handler is not None:
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
# fall back to app handlers
|
# fall back to app handlers
|
||||||
return find_superclass(self.error_handler_spec[None].get(code))
|
return find_handler(self.error_handler_spec[None].get(code))
|
||||||
|
|
||||||
def handle_http_exception(self, e):
|
def handle_http_exception(self, e):
|
||||||
"""Handles an HTTP exception. By default this will invoke the
|
"""Handles an HTTP exception. By default this will invoke the
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ def test_error_handler_subclass():
|
||||||
def registered_test():
|
def registered_test():
|
||||||
raise ChildExceptionRegistered()
|
raise ChildExceptionRegistered()
|
||||||
|
|
||||||
|
|
||||||
c = app.test_client()
|
c = app.test_client()
|
||||||
|
|
||||||
assert c.get('/parent').data == b'parent'
|
assert c.get('/parent').data == b'parent'
|
||||||
|
|
@ -76,7 +75,6 @@ def test_error_handler_http_subclass():
|
||||||
def unregistered_test():
|
def unregistered_test():
|
||||||
raise ForbiddenSubclassUnregistered()
|
raise ForbiddenSubclassUnregistered()
|
||||||
|
|
||||||
|
|
||||||
c = app.test_client()
|
c = app.test_client()
|
||||||
|
|
||||||
assert c.get('/forbidden').data == b'forbidden'
|
assert c.get('/forbidden').data == b'forbidden'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue