Skip to content

Commit

Permalink
Merge pull request spec-first#397 from LeenaBhegade/master
Browse files Browse the repository at this point in the history
pass encoding=utf-8 keyword argument to flask.json.dumps
  • Loading branch information
rafaelcaricio committed Feb 12, 2017
2 parents aa55d9e + aa246c7 commit fe6a625
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 73 deletions.
8 changes: 7 additions & 1 deletion connexion/decorators/produces.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging

import flask
import six
from flask import json

from .decorator import BaseDecorator
Expand Down Expand Up @@ -76,7 +77,12 @@ def dumps(data):
""" Central point where JSON serialization happens inside
Connexion.
"""
return "{}\n".format(json.dumps(data, indent=2))
if six.PY2:
json_content = json.dumps(data, indent=2, encoding="utf-8")
else:
json_content = json.dumps(data, indent=2)

return "{}\n".format(json_content)

def __call__(self, function):
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/api/test_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ def route2():
def test_resolve_method(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/resolver-test/method') # type: flask.Response
assert resp.data.decode() == '"DummyClass"\n'
assert resp.data.decode('utf-8', 'replace') == '"DummyClass"\n'


def test_resolve_classmethod(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/resolver-test/classmethod') # type: flask.Response
assert resp.data.decode() == '"DummyClass"\n'
assert resp.data.decode('utf-8', 'replace') == '"DummyClass"\n'


def test_add_api_with_function_resolver_function_is_wrapped(simple_api_spec_dir):
Expand Down
14 changes: 7 additions & 7 deletions tests/api/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def test_errors(problem_app):
greeting404 = app_client.get('/v1.0/greeting') # type: flask.Response
assert greeting404.content_type == 'application/problem+json'
assert greeting404.status_code == 404
error404 = json.loads(greeting404.data.decode('utf-8'))
error404 = json.loads(greeting404.data.decode('utf-8', 'replace'))
assert error404['type'] == 'about:blank'
assert error404['title'] == 'Not Found'
assert error404['detail'] == 'The requested URL was not found on the server. ' \
Expand All @@ -18,7 +18,7 @@ def test_errors(problem_app):
get_greeting = app_client.get('/v1.0/greeting/jsantos') # type: flask.Response
assert get_greeting.content_type == 'application/problem+json'
assert get_greeting.status_code == 405
error405 = json.loads(get_greeting.data.decode('utf-8'))
error405 = json.loads(get_greeting.data.decode('utf-8', 'replace'))
assert error405['type'] == 'about:blank'
assert error405['title'] == 'Method Not Allowed'
assert error405['detail'] == 'The method is not allowed for the requested URL.'
Expand All @@ -28,7 +28,7 @@ def test_errors(problem_app):
get500 = app_client.get('/v1.0/except') # type: flask.Response
assert get500.content_type == 'application/problem+json'
assert get500.status_code == 500
error500 = json.loads(get500.data.decode('utf-8'))
error500 = json.loads(get500.data.decode('utf-8', 'replace'))
assert error500['type'] == 'about:blank'
assert error500['title'] == 'Internal Server Error'
assert error500['detail'] == 'The server encountered an internal error and was unable to complete your request. ' \
Expand All @@ -40,7 +40,7 @@ def test_errors(problem_app):
assert get_problem.content_type == 'application/problem+json'
assert get_problem.status_code == 418
assert get_problem.headers['x-Test-Header'] == 'In Test'
error_problem = json.loads(get_problem.data.decode('utf-8'))
error_problem = json.loads(get_problem.data.decode('utf-8', 'replace'))
assert error_problem['type'] == 'http://www.example.com/error'
assert error_problem['title'] == 'Some Error'
assert error_problem['detail'] == 'Something went wrong somewhere'
Expand All @@ -50,7 +50,7 @@ def test_errors(problem_app):
get_problem2 = app_client.get('/v1.0/other_problem') # type: flask.Response
assert get_problem2.content_type == 'application/problem+json'
assert get_problem2.status_code == 418
error_problem2 = json.loads(get_problem2.data.decode('utf-8'))
error_problem2 = json.loads(get_problem2.data.decode('utf-8', 'replace'))
assert error_problem2['type'] == 'about:blank'
assert error_problem2['title'] == 'Some Error'
assert error_problem2['detail'] == 'Something went wrong somewhere'
Expand All @@ -63,12 +63,12 @@ def test_errors(problem_app):

custom_problem = app_client.get('/v1.0/customized_problem_response')
assert custom_problem.status_code == 403
problem_body = json.loads(custom_problem.data.decode('utf-8'))
problem_body = json.loads(custom_problem.data.decode('utf-8', 'replace'))
assert 'amount' in problem_body
assert problem_body['amount'] == 23.

problem_as_exception = app_client.get('/v1.0/problem_exception_with_extra_args')
assert problem_as_exception.status_code == 400
problem_as_exception_body = json.loads(problem_as_exception.data.decode('utf-8'))
problem_as_exception_body = json.loads(problem_as_exception.data.decode('utf-8', 'replace'))
assert 'age' in problem_as_exception_body
assert problem_as_exception_body['age'] == 30
2 changes: 1 addition & 1 deletion tests/api/test_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_header_not_returned(simple_app):
response = app_client.post('/v1.0/goodday/noheader', data={}) # type: flask.Response
assert response.status_code == 500 # view_func has not returned what was promised in spec
assert response.content_type == 'application/problem+json'
data = json.loads(response.data.decode('utf-8'))
data = json.loads(response.data.decode('utf-8', 'replace'))
assert data['type'] == 'about:blank'
assert data['title'] == 'Response headers do not conform to specification'
assert data['detail'] == "Keys in header don't match response specification. Difference: Location"
Expand Down
68 changes: 34 additions & 34 deletions tests/api/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ def test_array_query_param(simple_app):
headers = {'Content-type': 'application/json'}
url = '/v1.0/test_array_csv_query_param?items=one,two,three'
response = app_client.get(url, headers=headers)
array_response = json.loads(response.data.decode()) # type: [str]
array_response = json.loads(response.data.decode('utf-8', 'replace')) # type: [str]
assert array_response == ['one', 'two', 'three']
url = '/v1.0/test_array_pipes_query_param?items=1|2|3'
response = app_client.get(url, headers=headers)
array_response = json.loads(response.data.decode()) # type: [int]
array_response = json.loads(response.data.decode('utf-8', 'replace')) # type: [int]
assert array_response == [1, 2, 3]
url = '/v1.0/test_array_unsupported_query_param?items=1;2;3'
response = app_client.get(url, headers=headers)
array_response = json.loads(response.data.decode()) # [str] unsupported collectionFormat
array_response = json.loads(response.data.decode('utf-8', 'replace')) # [str] unsupported collectionFormat
assert array_response == ["1;2;3"]


Expand All @@ -66,14 +66,14 @@ def test_strict_extra_query_param(strict_app):
url = '/v1.0/test_parameter_validation?extra_parameter=true'
resp = app_client.get(url, headers=headers)
assert resp.status_code == 400
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response['detail'] == "Extra query parameter(s) extra_parameter not in spec"


def test_path_parameter_someint(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-int-path/123') # type: flask.Response
assert resp.data.decode() == '"int"\n'
assert resp.data.decode('utf-8', 'replace') == '"int"\n'

# non-integer values will not match Flask route
resp = app_client.get('/v1.0/test-int-path/foo') # type: flask.Response
Expand All @@ -83,7 +83,7 @@ def test_path_parameter_someint(simple_app):
def test_path_parameter_somefloat(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-float-path/123.45') # type: flask.Response
assert resp.data.decode() == '"float"\n'
assert resp.data.decode('utf-8' , 'replace') == '"float"\n'

# non-float values will not match Flask route
resp = app_client.get('/v1.0/test-float-path/123,45') # type: flask.Response
Expand All @@ -94,20 +94,20 @@ def test_default_param(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-default-query-parameter')
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response['app_name'] == 'connexion'


def test_falsy_param(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-falsy-param', query_string={'falsy': 0})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response == 0

resp = app_client.get('/v1.0/test-falsy-param')
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response == 1


Expand All @@ -116,15 +116,15 @@ def test_formdata_param(simple_app):
resp = app_client.post('/v1.0/test-formData-param',
data={'formData': 'test'})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response == 'test'


def test_formdata_bad_request(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.post('/v1.0/test-formData-param')
assert resp.status_code == 400
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response['detail'] == "Missing formdata parameter 'formData'"


Expand All @@ -149,7 +149,7 @@ def test_strict_formdata_extra_param(strict_app):
data={'formData': 'test',
'extra_formData': 'test'})
assert resp.status_code == 400
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response['detail'] == "Extra formData parameter(s) extra_formData not in spec"


Expand All @@ -158,15 +158,15 @@ def test_formdata_file_upload(simple_app):
resp = app_client.post('/v1.0/test-formData-file-upload',
data={'formData': (BytesIO(b'file contents'), 'filename.txt')})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response == {'filename.txt': 'file contents'}


def test_formdata_file_upload_bad_request(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.post('/v1.0/test-formData-file-upload')
assert resp.status_code == 400
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response['detail'] == "Missing formdata parameter 'formData'"


Expand All @@ -184,34 +184,34 @@ def test_bool_as_default_param(simple_app):

resp = app_client.get('/v1.0/test-bool-param', query_string={'thruthiness': True})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response is True


def test_bool_param(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-bool-param', query_string={'thruthiness': True})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response is True

resp = app_client.get('/v1.0/test-bool-param', query_string={'thruthiness': False})
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response is False


def test_bool_array_param(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-bool-array-param?thruthiness=true,true,true')
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response is True

app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-bool-array-param?thruthiness=true,true,false')
assert resp.status_code == 200
response = json.loads(resp.data.decode())
response = json.loads(resp.data.decode('utf-8', 'replace'))
assert response is False

app_client = simple_app.app.test_client()
Expand All @@ -236,7 +236,7 @@ def test_parameters_defined_in_path_level(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/parameters-in-root-path?title=nice-get')
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == ["nice-get"]
assert json.loads(resp.data.decode('utf-8', 'replace')) == ["nice-get"]

resp = app_client.get('/v1.0/parameters-in-root-path')
assert resp.status_code == 400
Expand All @@ -245,59 +245,59 @@ def test_parameters_defined_in_path_level(simple_app):
def test_array_in_path(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/test-array-in-path/one_item')
assert json.loads(resp.data.decode()) == ["one_item"]
assert json.loads(resp.data.decode('utf-8', 'replace')) == ["one_item"]

resp = app_client.get('/v1.0/test-array-in-path/one_item,another_item')
assert json.loads(resp.data.decode()) == ["one_item", "another_item"]
assert json.loads(resp.data.decode('utf-8', 'replace')) == ["one_item", "another_item"]


def test_nullable_parameter(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/nullable-parameters?time_start=null')
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'

resp = app_client.get('/v1.0/nullable-parameters?time_start=None')
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'

time_start = 1010
resp = app_client.get(
'/v1.0/nullable-parameters?time_start={}'.format(time_start))
assert json.loads(resp.data.decode()) == time_start
assert json.loads(resp.data.decode('utf-8', 'replace')) == time_start

resp = app_client.post('/v1.0/nullable-parameters', data={"post_param": 'None'})
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'

resp = app_client.post('/v1.0/nullable-parameters', data={"post_param": 'null'})
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'

resp = app_client.put('/v1.0/nullable-parameters', data="null")
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'

resp = app_client.put('/v1.0/nullable-parameters', data="None")
assert json.loads(resp.data.decode()) == 'it was None'
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'


def test_args_kwargs(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.get('/v1.0/query-params-as-kwargs')
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == {}
assert json.loads(resp.data.decode('utf-8', 'replace')) == {}

resp = app_client.get('/v1.0/query-params-as-kwargs?foo=a&bar=b')
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == {'foo': 'a'}
assert json.loads(resp.data.decode('utf-8', 'replace')) == {'foo': 'a'}


def test_param_sanitization(simple_app):
app_client = simple_app.app.test_client()
resp = app_client.post('/v1.0/param-sanitization')
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == {}
assert json.loads(resp.data.decode('utf-8', 'replace')) == {}

resp = app_client.post('/v1.0/param-sanitization?$query=queryString',
data={'$form': 'formString'})
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == {
assert json.loads(resp.data.decode('utf-8', 'replace')) == {
'query': 'queryString',
'form': 'formString',
}
Expand All @@ -308,4 +308,4 @@ def test_param_sanitization(simple_app):
data=json.dumps(body),
headers={'Content-Type': 'application/json'})
assert resp.status_code == 200
assert json.loads(resp.data.decode()) == body
assert json.loads(resp.data.decode('utf-8', 'replace')) == body
Loading

0 comments on commit fe6a625

Please sign in to comment.