Browse Source

Recursively traverse MRO of exception

pull/1431/head
Markus Unterwaditzer 10 years ago
parent
commit
7d506f2408
  1. 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
# try blueprint handlers queue.extend(cls.__mro__)
handler = find_superclass(self.error_handler_spec.get(request.blueprint, {}).get(code))
# try blueprint handlers
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

Loading…
Cancel
Save