mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-08 16:53:23 +00:00
Fix for Serialization errors with JSON adapter
This patch aims to fix the issue#222, where json data in request can not be serialized because of TypeError in py3
This commit is contained in:
committed by
Kevin McCarthy
parent
528c9e7b1a
commit
9daf301deb
@@ -2,7 +2,8 @@
|
||||
import pytest
|
||||
|
||||
from vcr.compat import mock
|
||||
from vcr.serialize import deserialize
|
||||
from vcr.request import Request
|
||||
from vcr.serialize import deserialize, serialize
|
||||
from vcr.serializers import yamlserializer, jsonserializer
|
||||
|
||||
|
||||
@@ -83,3 +84,50 @@ def test_deserialize_py2py3_yaml_cassette(tmpdir, req_body, expect):
|
||||
def test_serialize_constructs_UnicodeDecodeError(mock_dumps):
|
||||
with pytest.raises(UnicodeDecodeError):
|
||||
jsonserializer.serialize({})
|
||||
|
||||
|
||||
def test_serialize_empty_request():
|
||||
request = Request(
|
||||
method='POST',
|
||||
uri='http://localhost/',
|
||||
body='',
|
||||
headers={},
|
||||
)
|
||||
|
||||
serialize(
|
||||
{'requests': [request], 'responses': [{}]},
|
||||
jsonserializer
|
||||
)
|
||||
|
||||
|
||||
def test_serialize_json_request():
|
||||
request = Request(
|
||||
method='POST',
|
||||
uri='http://localhost/',
|
||||
body="{'hello': 'world'}",
|
||||
headers={},
|
||||
)
|
||||
|
||||
serialize(
|
||||
{'requests': [request], 'responses': [{}]},
|
||||
jsonserializer
|
||||
)
|
||||
|
||||
|
||||
def test_serialize_binary_request():
|
||||
msg = "Does this HTTP interaction contain binary data?"
|
||||
|
||||
request = Request(
|
||||
method='POST',
|
||||
uri='http://localhost/',
|
||||
body=b'\x8c',
|
||||
headers={},
|
||||
)
|
||||
|
||||
try:
|
||||
serialize(
|
||||
{'requests': [request], 'responses': [{}]},
|
||||
jsonserializer
|
||||
)
|
||||
except (UnicodeDecodeError, TypeError) as exc:
|
||||
assert msg in str(exc)
|
||||
|
||||
@@ -50,7 +50,7 @@ def deserialize(cassette_string, serializer):
|
||||
|
||||
def serialize(cassette_dict, serializer):
|
||||
interactions = ([{
|
||||
'request': request._to_dict(),
|
||||
'request': compat.convert_to_unicode(request._to_dict()),
|
||||
'response': compat.convert_to_unicode(response),
|
||||
} for request, response in zip(
|
||||
cassette_dict['requests'],
|
||||
|
||||
@@ -37,19 +37,43 @@ def convert_body_to_bytes(resp):
|
||||
return resp
|
||||
|
||||
|
||||
def _convert_string_to_unicode(string):
|
||||
"""
|
||||
If the string is bytes, decode it to a string (for python3 support)
|
||||
"""
|
||||
result = string
|
||||
|
||||
try:
|
||||
if string is not None and not isinstance(string, six.text_type):
|
||||
result = string.decode('utf-8')
|
||||
except (TypeError, UnicodeDecodeError, AttributeError):
|
||||
# Sometimes the string actually is binary or StringIO object,
|
||||
# so if you can't decode it, just give up.
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def convert_body_to_unicode(resp):
|
||||
"""
|
||||
If the request body is bytes, decode it to a string (for python3 support)
|
||||
If the request or responses body is bytes, decode it to a string
|
||||
(for python3 support)
|
||||
"""
|
||||
try:
|
||||
if not isinstance(resp['body']['string'], six.text_type):
|
||||
resp['body']['string'] = resp['body']['string'].decode('utf-8')
|
||||
except (KeyError, TypeError, UnicodeDecodeError):
|
||||
# The thing we were converting either wasn't a dictionary or didn't
|
||||
# have the keys we were expecting. Some of the tests just serialize
|
||||
# and deserialize a string.
|
||||
if type(resp) is not dict:
|
||||
# Some of the tests just serialize and deserialize a string.
|
||||
return _convert_string_to_unicode(resp)
|
||||
else:
|
||||
body = resp.get('body')
|
||||
|
||||
if body is not None:
|
||||
try:
|
||||
body['string'] = _convert_string_to_unicode(
|
||||
body['string']
|
||||
)
|
||||
except (KeyError, TypeError, AttributeError):
|
||||
# The thing we were converting either wasn't a dictionary or
|
||||
# didn't have the keys we were expecting.
|
||||
# For example request object has no 'string' key.
|
||||
resp['body'] = _convert_string_to_unicode(body)
|
||||
|
||||
# Also, sometimes the thing actually is binary, so if you can't decode
|
||||
# it, just give up.
|
||||
pass
|
||||
return resp
|
||||
|
||||
@@ -9,16 +9,21 @@ def deserialize(cassette_string):
|
||||
|
||||
|
||||
def serialize(cassette_dict):
|
||||
error_message = (
|
||||
"Does this HTTP interaction contain binary data? "
|
||||
"If so, use a different serializer (like the yaml serializer) "
|
||||
"for this request?"
|
||||
)
|
||||
|
||||
try:
|
||||
return json.dumps(cassette_dict, indent=4)
|
||||
except UnicodeDecodeError as original:
|
||||
except UnicodeDecodeError as original: # py2
|
||||
raise UnicodeDecodeError(
|
||||
original.encoding,
|
||||
b"Error serializing cassette to JSON",
|
||||
original.start,
|
||||
original.end,
|
||||
original.args[-1] +
|
||||
("Does this HTTP interaction contain binary data? "
|
||||
"If so, use a different serializer (like the yaml serializer) "
|
||||
"for this request?")
|
||||
original.args[-1] + error_message
|
||||
)
|
||||
except TypeError as original: # py3
|
||||
raise TypeError(error_message)
|
||||
|
||||
Reference in New Issue
Block a user