8000 Merge pull request #59 from dutronlabs/master · flask-api/flask-api@5575a62 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5575a62

Browse files
authored
Merge pull request #59 from dutronlabs/master
fix for #58
2 parents ff5c08d + 9237425 commit 5575a62

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

flask_api/app.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from werkzeug.exceptions import HTTPException
1111
import re
1212
import sys
13+
from flask_api.compat import is_flask_legacy
1314

1415

1516
api_resources = Blueprint(
@@ -88,9 +89,14 @@ def handle_user_exception(self, e):
8889
if handlers is not None:
8990
blueprint_handlers = handlers.get(None, ())
9091
app_handlers = self.error_handler_spec[None].get(None, ())
91-
for typecheck, handler in chain(blueprint_handlers, app_handlers):
92-
if isinstance(e, typecheck):
93-
return handler(e)
92+
if is_flask_legacy():
93+
for typecheck, handler in chain(blueprint_handlers, app_handlers):
94+
if isinstance(e, typecheck):
95+
return handler(e)
96+
else:
97+
for typecheck, handler in chain(blueprint_handlers.items(), app_handlers.items()):
98+
if isinstance(e, typecheck):
99+
return handler(e)
94100

95101
reraise(exc_type, exc_value, tb)
96102

flask_api/compat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import unicode_literals, absolute_import
3+
from flask import __version__ as flask_version
34

45
# Markdown is optional
56
try:
@@ -16,5 +17,11 @@ def apply_markdown(text):
1617
md = markdown.Markdown(extensions=extensions, safe_mode=safe_mode)
1718
return md.convert(text)
1819

20+
1921
except ImportError:
2022
apply_markdown = None
23+
24+
25+
def is_flask_legacy():
26+
v = flask_version.split(".")
27+
return int(v[0]) == 0 and int(v[1]) < 11

flask_api/tests/test_app.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# coding: utf8
22
from __future__ import unicode_literals
3-
from flask import abort, make_response, request
3+
from flask import abort, make_response, request, jsonify
44
from flask_api.decorators import set_renderers
55
from flask_api import exceptions, renderers, status, FlaskAPI
66
import json
@@ -19,6 +19,30 @@ class JSONVersion2(renderers.JSONRenderer):
1919
media_type = 'application/json; api-version="2.0"'
2020

2121

22+
# This is being used to test issue #58, source is taken from flask apierrors doc page
23+
class InvalidUsage(Exception):
24+
status_code = 400
25+
26+
def __init__(self, message, status_code=None, payload=None):
27+
Exception.__init__(self)
28+
self.message = message
29+
if status_code is not None:
30+
self.status_code = status_code
31+
self.payload = payload
32+
33+
def to_dict(self):
34+
rv = dict(self.payload or ())
35+
rv['message'] = self.message
36+
return rv
37+
38+
39+
@app.errorhandler(InvalidUsage)
40+
def handle_invalid_usage(error):
41+
response = jsonify(error.to_dict())
42+
response.status_code = error.status_code
43+
return response
44+
45+
2246
@app.route('/set_status_and_headers/')
2347
def set_status_and_headers():
2448
headers = {'Location': 'http://example.com/456'}
@@ -43,6 +67,16 @@ def api_exception():
4367
raise exceptions.PermissionDenied()
4468

4569

70+
@app.route('/custom_exception/')
71+
def custom_exception():
72+
raise InvalidUsage('Invalid usage test.', status_code=410)
73+
74+
75+
@app.route('/custom_exception_no_code/')
76+
def custom_exception_no_status_code():
77+
raise InvalidUsage('Invalid usage test.')
78+
79+
4680
@app.route('/abort_view/')
4781
def abort_view():
4882
abort(status.HTTP_403_FORBIDDEN)
@@ -95,6 +129,18 @@ def test_api_exception(self):
95129
expected = '{"message": "You do not have permission to perform this action."}'
96130
self.assertEqual(response.get_data().decode('utf8'), expected)
97131

132+
def test_custom_exception(self):
133+
with app.test_client() as client:
134+
response = client.get('/custom_exception/')
135+
self.assertEqual(response.status_code, status.HTTP_410_GONE)
136+
self.assertEqual(response.content_type, 'application/json')
137+
138+
def test_custom_exception_default_code(self):
139+
with app.test_client() as client:
140+
response = client.get('/custom_exception_no_code/')
141+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
142+
self.assertEqual(response.content_type, 'application/json')
143+
98144
def test_abort_view(self):
99145
with app.test_client() as client:
100146
response = client.get('/abort_view/')

0 commit comments

Comments
 (0)
0