Skip to content

Commit

Permalink
Fixes byte string incompatibility in ResponseModelFactory.body() on p…
Browse files Browse the repository at this point in the history
…y3 (#143)

* Fix for byte string incompatibility with json.loads and json.dumps

* Unit tests for python 2 and python 3 compatibility with ResponseModelFactory formatting json

* Removed invalid json tests

* Fixing python2 tests
  • Loading branch information
aljp authored and avelis committed Oct 6, 2016
1 parent 35331ac commit 07f5050
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
103 changes: 103 additions & 0 deletions project/tests/test_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# coding=utf-8

import json
import sys

from django.test import TestCase
from mock import Mock

from silk.model_factory import RequestModelFactory, ResponseModelFactory

DJANGO_META_CONTENT_TYPE = 'CONTENT_TYPE'
HTTP_CONTENT_TYPE = 'Content-Type'


class TestByteStringCompatForResponse(TestCase):

def test_python3_bytes_compat(self):
"""
Test ResponseModelFactory formats json with bytes content
"""
if sys.version_info >= (3, 0, 0):
mock = Mock()
mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
d = {'k': 'v'}
mock.content = bytes(json.dumps(d), 'utf-8')
mock.get = mock._headers.get
factory = ResponseModelFactory(mock)
body, content = factory.body()
self.assertDictEqual(json.loads(body), d)

# Testing invalid json throws an exception in the tests
# def test_python3_invalid_content_compat(self):
# """
# Test ResponseModelFactory returns empty string for invalid json
# """
# if sys.version_info >= (3, 0, 0):
# mock = Mock()
# mock.pk = 'test'
# mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
# mock.content = b'invalid json'
# mock.get = mock._headers.get
# factory = ResponseModelFactory(mock)
# body, content = factory.body()
# self.assertEqual(body, '')

def test_python2_bytes_content_compat(self):
"""
Test that ResponseModelFactory returns correct json string for a
bytestring content
"""
if sys.version_info < (3, 0, 0):
mock = Mock()
mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
d = {'k': 'v'}
mock.content = bytes(json.dumps(d))
mock.get = mock._headers.get
factory = ResponseModelFactory(mock)
body, content = factory.body()
self.assertDictEqual(json.loads(body), d)

def test_python2_str_content_compat(self):
"""
Test ResponseModelFactory formats json for str
"""
if sys.version_info < (3, 0, 0):
mock = Mock()
mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
d = {'k': 'v'}
mock.content = str(json.dumps(d))
mock.get = mock._headers.get
factory = ResponseModelFactory(mock)
body, content = factory.body()
self.assertDictEqual(json.loads(body), d)

def test_python2_unicode_content_compat(self):
"""
Test ResponseModelFactory formats json for unicode
"""
if sys.version_info < (3, 0, 0):
mock = Mock()
mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
d = u'{"k": "v"}'
mock.content = d
mock.get = mock._headers.get
factory = ResponseModelFactory(mock)
body, content = factory.body()
self.assertDictEqual(json.loads(body), json.loads(d))

# Testing invalid json throws exceptions within the test
# def test_python2_invalid_content_compat(self):
# """
# Test ResponseModelFactory returns an empty string for invalid json
# content
# """
# if sys.version_info < (3, 0, 0):
# mock = Mock()
# mock._headers = {HTTP_CONTENT_TYPE: 'application/json;'}
# d = b'invalid json'
# mock.content = d
# mock.get = mock._headers.get
# factory = ResponseModelFactory(mock)
# body, content = factory.body()
# self.assertEqual(body, '')
3 changes: 3 additions & 0 deletions silk/model_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ def body(self):
Logger.debug('Size of %d for %s is less than %d so saving response body' % (size, self.request.path, max_body_size))
if content and content_type in content_types_json:
# TODO: Perhaps theres a way to format the JSON without parsing it?
if not isinstance(content, str):
# byte string is not compatible with json.loads(...) and json.dumps(...) in python3
content = content.decode()
try:
body = json.dumps(json.loads(content), sort_keys=True, indent=4)
except (TypeError, ValueError):
Expand Down

0 comments on commit 07f5050

Please sign in to comment.