From 423b42f60a24999d8c07ecebda3b225e97369b7d Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Wed, 30 May 2018 14:19:30 +0200 Subject: [PATCH] restapi/client: don't use DRF parser for parsing The DRF parser expect a file-like object containing bytes while we are passing it a unicode string. The outcome of this is slumber serialization not working and returning plain bytes instead of unserialized data. The fix is trivial and it's just using slumber code for parsing instead of providing our own. For reference after making slumber dump exceptions instead of swallowing here's the root cause: Traceback (most recent call last): [celery.redirected:235] File "/venv/lib/python3.5/site-packages/slumber/__init__.py", line 134, in _try_to_serialize_response return stype.loads(resp.content.decode(encoding)) [celery.redirected:235] File "/home/readthedocs/restapi/client.py", line 28, in loads return JSONParser().parse(data) [celery.redirected:235] File "/venv/lib/python3.5/site-packages/rest_framework/parsers.py", line 66, in parse return json.load(decoded_stream) [celery.redirected:235] File "/usr/lib/python3.5/json/__init__.py", line 265, in load return loads(fp.read(), [celery.redirected:235] File "/usr/lib/python3.5/codecs.py", line 493, in read newdata = self.stream.read() [celery.redirected:235] AttributeError: 'str' object has no attribute 'read' [celery.redirected:235] Fix #4157 --- readthedocs/restapi/client.py | 6 +---- .../rtd_tests/tests/test_restapi_client.py | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 readthedocs/rtd_tests/tests/test_restapi_client.py diff --git a/readthedocs/restapi/client.py b/readthedocs/restapi/client.py index aefbcd3f8c4..1a70bbc9def 100644 --- a/readthedocs/restapi/client.py +++ b/readthedocs/restapi/client.py @@ -10,7 +10,6 @@ import requests from django.conf import settings from requests_toolbelt.adapters import host_header_ssl -from rest_framework.parsers import JSONParser from rest_framework.renderers import JSONRenderer from slumber import API, serialize @@ -24,13 +23,10 @@ class DrfJsonSerializer(serialize.JsonSerializer): - """Additional serialization help from the DRF parser/renderer.""" + """Additional serialization help from the DRF renderer""" key = 'json-drf' - def loads(self, data): - return JSONParser().parse(data) - def dumps(self, data): return JSONRenderer().render(data) diff --git a/readthedocs/rtd_tests/tests/test_restapi_client.py b/readthedocs/rtd_tests/tests/test_restapi_client.py new file mode 100644 index 00000000000..88906fdc10f --- /dev/null +++ b/readthedocs/rtd_tests/tests/test_restapi_client.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import ( + absolute_import, unicode_literals) + +from django.test import TestCase + +from readthedocs.restapi.client import DrfJsonSerializer + + +class TestDrfJsonSerializer(TestCase): + data = { + 'proper': 'json' + } + serialized_data = '{"proper":"json"}' + + def test_serializer_loads_json(self): + serializer = DrfJsonSerializer() + data = serializer.loads(self.serialized_data) + self.assertDictEqual(data, self.data) + + def test_serializer_dumps_json(self): + serializer = DrfJsonSerializer() + serialized_data = serializer.dumps(self.data) + self.assertJSONEqual(serialized_data, self.serialized_data)