Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magnuschill/ff152f02fe20f31a3cf738b4f9d5ab2f to your computer and use it in GitHub Desktop.
Save magnuschill/ff152f02fe20f31a3cf738b4f9d5ab2f to your computer and use it in GitHub Desktop.
import flask_restful
import functools
class Api(flask_restful.Api):
"""
Patch Flask-style custom error handling into the Flask-RESTful api class.
"""
def __init__(self, *args, **kwargs):
super(Api, self).__init__(*args, **kwargs)
self._errorhandlers = []
def errorhandler(self, exception_type):
"""
Defined handlers for exceptions. Example:
@api.errorhandler(ServerError):
def handle_server_error(error):
response = flask.jsonify({'message': error.message})
response.status_code = error.status_code
return response
"""
def wrapper(func):
self._errorhandlers.append((exception_type, func))
# Sort error handlers to have sub exceptions first, so that those
# take preference over base exceptions.
self._errorhandlers = sorted(
self._errorhandlers,
key= functools.cmp_to_key(self._inheritance_comparator))
#print(self._errorhandlers)
return func
return wrapper
def handle_error(self, error, previous_errors=None):
# Keep track of previous errors in the current chain of exception
# handling in order to prevent infinite cycles that would occur if two
# error handler raise the exception handled by the other.
previous_errors = previous_errors or []
previous_errors.append(type(error))
# Try to find the first custom handler for the occured exception.
for exception_type, handler in self._errorhandlers:
if not isinstance(error, exception_type):
continue
try:
return handler(error)
except Exception as new_error:
if type(new_error) not in previous_errors:
return self.handle_error(new_error, previous_errors)
break
# If no matching handler was found or an infinite cycle is detected,
# fall back to Flask-RESTful's error handling.
return super(Api, self).handle_error(error)
@staticmethod
def _inheritance_comparator(lhs, rhs):
lhs_sub = issubclass(lhs[0], rhs[0])
rhs_sub = issubclass(lhs[0], rhs[0])
if lhs_sub and not rhs_sub:
return -1
if rhs_sub and not lhs_sub:
return 1
return 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment