Flask-Exceptions

A base set of API Exceptions for Flask apps


Keywords
flask, exceptions, api
License
MIT
Install
pip install Flask-Exceptions==1.2.3

Documentation

Flask-Exceptions

Build Status Coverage Status

Requirements

This project requires Python 3 (tested with 3.3-3.6) and Flask 0.12

Installation

To install it, simply run

pip install flask-exceptions

Usage

Import it and wrap app

from flask import Flask
from flask_exceptions import AddExceptions

app = Flask(__name__)
exceptions = AddExceptions(app)

You also need to define the Flask app error handler to catch the base exception used (APIException).

from flask import jsonify
from flask_exceptions import APIException

@app.errorhandler(APIException)
def handle_exceptions(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response

You may add a statsd (pystatsd interface) counters to exceptions by passing a statsd kwarg to the initialization. It can be any counter compliant with the statsd(https://pypi.python.org/pypi/statsd) interface. You can use this extension with the Flask-StatsDClient(https://pypi.python.org/pypi/Flask-StatsDClient) simply like:

from flask import Flask
from flask_exceptions import AddExceptions
from flask_statsdclient import StatsDClient

app = Flask(__name__)
statsd = StatsDClient(app)
exceptions = AddExceptions(app, statsd=statsd)

The default StatsD counter will be in the form exceptions.xxx with xxx being the status code. This does not take into account any prefix you added when instantiating StatsDClient itself.

You may customize the prefix of the StatsD key by setting EXCEPTION_PREFIX in your Flask app config. The default prefix is simple exceptions.

Also you may configure whether the error returned to the client includes a message or not by setting EXCEPTION_MESSAGE to False in your Flask app config. The default is True.

When using one of the custom exceptions, you may pass an optional message and payload to the exception constructor.

from app import exceptions

exceptions.bad_request()  # returns 400 with default message (if enabled)

exceptions.not_found('Nothing to see here')  # returns a 404 with custom error message

exceptions.not_found(message='Nothing to see here')  # also returns a 404 with custom error message, using the `message` kwarg

exceptions.conflict('Race condition!', payload={'error': '4-8-15-16-23-42'})  # custom error & payload

Currently supported HTTP errors include 400 - bad_request(), 401 - unauthorized(), 403 - forbidden(), 404 - not_found(), 409 - conflict(), 410 - gone(), 415 - unsupported_media(), and 422 - unprocessable_entity()

Development

This project was written and tested with Python 3. Our builds currently support Python 3.3 to 3.6.

On a mac you can use the following commands to get up and running.

brew install python3

otherwise run

brew upgrade python3

to make sure you have an up to date version.

This project uses pip-tools for dependency management. Install pip-tools

pip3 install pip-tools

setup the project env

python -m venv venv
pip install -r requirements.txt -r requirements-dev.txt

Make sure the following environment variables are set

export PYTHONPATH=`pwd`

Then load your virtualenv

source venv/bin/activate

Running tests

./linters.sh && coverage run --source=flask_exceptions/ setup.py test

Before committing any code

We have a pre-commit hook each dev needs to setup. You can symlink it to run before each commit by changing directory to the repo and running

cd .git/hooks
ln -s ../../pre-commit pre-commit