diff --git a/setup.py b/setup.py index fbee2bb..4e2b449 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ 'PyFxA', 'requests', 'requests-hawk', + 'six', ] setup(name='syncclient', diff --git a/syncclient/client.py b/syncclient/client.py index 98eb1db..3b4b689 100644 --- a/syncclient/client.py +++ b/syncclient/client.py @@ -1,5 +1,7 @@ from hashlib import sha256 from binascii import hexlify +import json +import six import sys import requests @@ -35,7 +37,9 @@ def get_browserid_assertion(login, password, fxa_server_url=FXA_SERVER_URL, session = client.login(login, password, keys=True) bid_assertion = session.get_identity_assertion(tokenserver_url) _, keyB = session.fetch_keys() - return bid_assertion, hexlify(sha256(keyB.encode('utf-8')).digest()[0:16]) + if isinstance(keyB, six.text_type): # pragma: no cover + keyB = keyB.encode('utf-8') + return bid_assertion, hexlify(sha256(keyB).digest()[0:16]) class SyncClientError(Exception): @@ -250,10 +254,20 @@ def put_record(self, collection, record, **kwargs): Note that the server may impose a limit on the amount of data submitted for storage in a single BSO. """ + # XXX: Workaround until request-hawk supports the json parameter. (#17) + if isinstance(record, six.string_types): + record = json.loads(record) record = record.copy() record_id = record.pop('id') + headers = {} + if 'headers' in kwargs: + headers = kwargs.pop('headers') + + headers['Content-Type'] = 'application/json; charset=utf-8' + return self._request('put', '/storage/%s/%s' % ( - collection.lower(), record_id), json=record, **kwargs) + collection.lower(), record_id), data=json.dumps(record), + headers=headers, **kwargs) def post_records(self, collection, records, **kwargs): """ diff --git a/tests/test_client.py b/tests/test_client.py index 74c462d..4bbd78d 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -381,16 +381,26 @@ def test_put_record(self): self.client.put_record('myCollection', record) self.client._request.assert_called_with( 'put', '/storage/mycollection/1234', - json={'foo': 'bar'}) + data='{"foo": "bar"}', + headers={'Content-Type': 'application/json; charset=utf-8'}) + + def test_put_record_handle_json_string_parameter(self): + record = '{"id": 1234, "foo": "bar"}' + self.client.put_record('myCollection', record) + self.client._request.assert_called_with( + 'put', '/storage/mycollection/1234', + data='{"foo": "bar"}', + headers={'Content-Type': 'application/json; charset=utf-8'}) def test_put_record_can_receive_requests_parameters(self): record = {'id': 1234, 'foo': 'bar'} self.client.put_record('myCollection', record, - headers=mock.sentinel.headers) + headers={'Sentinel': 'true'}) self.client._request.assert_called_with( 'put', '/storage/mycollection/1234', - json={'foo': 'bar'}, - headers=mock.sentinel.headers) + data='{"foo": "bar"}', + headers={'Content-Type': 'application/json; charset=utf-8', + 'Sentinel': 'true'}) def test_put_record_doesnt_modify_the_passed_object(self): record = {'id': 1234, 'foo': 'bar'}