Source code for flask_resty.exceptions
import traceback
import flask
from werkzeug.exceptions import default_exceptions
from .utils import iter_validation_errors
# -----------------------------------------------------------------------------
[docs]class ApiError(Exception):
"""An API exception.
When raised, Flask-RESTy will send an HTTP response with the provided
`status_code` and the provided `errors` under the ``errors`` property as
JSON.
If :py:attr:`flask.Flask.debug` or :py:attr:`flask.Flask.testing` is True,
the body will also contain the full traceback under the ``debug`` property.
:param int status_code: The HTTP status code for the error response.
:param dict errors: A list of dict with error data.
"""
def __init__(self, status_code, *errors):
self.status_code = status_code
self.body = {"errors": errors or self.get_default_errors(status_code)}
if flask.current_app.debug or flask.current_app.testing:
self.body["debug"] = traceback.format_exc()
@classmethod
def from_http_exception(cls, exc):
return cls(exc.code, cls.get_error_from_http_exception(exc))
@classmethod
def get_default_errors(cls, status_code):
if status_code not in default_exceptions:
return ()
exc = default_exceptions[status_code]()
return (cls.get_error_from_http_exception(exc),)
@classmethod
def get_error_from_http_exception(cls, exc):
return {
"code": "_".join(word.lower() for word in exc.name.split()),
"detail": exc.description,
}
@classmethod
def from_validation_error(
cls, status_code, error, format_validation_error
):
return cls(
status_code,
*(
format_validation_error(message, path)
for message, path in iter_validation_errors(error.messages)
),
)
[docs] def update(self, additional):
"""Add additional metadata to the error.
Can be chained with further updates.
:param dict additional: The additional metadata
:return: The :py:class:`ApiError` that :py:meth:`update` was called on
:rtype: :py:class:`ApiError`
"""
for error in self.body["errors"]:
error.update(additional)
# Allow e.g. `raise e.update(additional)`.
return self
@property
def response(self):
if flask.current_app.config.get("RESTY_TRAP_API_ERRORS"):
raise self
return flask.jsonify(self.body), self.status_code