Skip to content

Commit

Permalink
Fix Python3 bugs
Browse files Browse the repository at this point in the history
This patch fixes three issues that were found running
functional tests with Python 3:

1. python-requests sets 'application/x-www-form-urlencoded' as
   content-type if the input is not a string object and no
   content-type is given.

2. Encoding of the headers is now only done if required. This
   prevents comparisons between unencoded headers and encoded
   prefixes and avoids unnecessary forloop-iterations.
   One unittest was extended to ensure it works for unencoded
   and encoded headers with or without the prefix.

3. Functional tests recently switched to using byte data for
   testing, thus the comparison needs to be a byte object as well.

Change-Id: I035f8b4b9c9ccdc79820b907770a48f86d0343b4
  • Loading branch information
Christian Schwede authored and anc committed May 21, 2014
1 parent e7dc854 commit 258420f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
17 changes: 10 additions & 7 deletions swiftclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,12 @@ def _encode_meta_headers(self, items):
for header, value in items:
value = encode_utf8(value)
header = header.lower()
for target_type in 'container', 'account', 'object':
prefix = 'x-%s-meta-' % target_type
if header.startswith(prefix):
header = encode_utf8(header)
if isinstance(header, six.string_types):
for target_type in 'container', 'account', 'object':
prefix = 'x-%s-meta-' % target_type
if header.startswith(prefix):
header = encode_utf8(header)
break
ret[header] = value
return ret

Expand Down Expand Up @@ -899,9 +901,8 @@ def put_object(url, token=None, container=None, name=None, contents=None,
:param chunk_size: chunk size of data to write; it defaults to 65536;
used only if the contents object has a 'read'
method, e.g. file-like objects, ignored otherwise
:param content_type: value to send as content-type header; if None, no
content-type will be set (remote end will likely try
to auto-detect it)
:param content_type: value to send as content-type header; if None, an
empty string value will be sent
:param headers: additional headers to include in the request, if any
:param http_conn: HTTP connection object (If None, it will create the
conn object)
Expand Down Expand Up @@ -940,6 +941,8 @@ def put_object(url, token=None, container=None, name=None, contents=None,
content_length = int(v)
if content_type is not None:
headers['Content-Type'] = content_type
else: # python-requests sets application/x-www-form-urlencoded otherwise
headers['Content-Type'] = ''
if not contents:
headers['Content-Length'] = '0'
if hasattr(contents, 'read'):
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/test_swiftclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def test_download_object(self):
self.containername, self.objectname,
resp_chunk_size=10)
self.assertTrue(isinstance(body, types.GeneratorType))
self.assertEqual(self.test_data, ''.join(body))
self.assertEqual(self.test_data, b''.join(body))

def test_post_account(self):
self.conn.post_account({'x-account-meta-data': 'Something'})
Expand Down
20 changes: 19 additions & 1 deletion tests/unit/test_swiftclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,16 @@ def test_params(self):
self.assertTrue(request_header['etag'], '1234-5678')
self.assertTrue(request_header['content-type'], 'text/plain')

def test_no_content_type(self):
conn = c.http_connection(u'http://www.test.com/')
resp = MockHttpResponse(status=200)
conn[1].getresponse = resp.fake_response
conn[1]._request = resp._fake_request

c.put_object(url='http://www.test.com', http_conn=conn)
request_header = resp.requests_params['headers']
self.assertEqual(request_header['content-type'], b'')


class TestPostObject(MockHttpTest):

Expand All @@ -746,7 +756,10 @@ def test_unicode_ok(self):
u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91')
text = u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91'
headers = {'X-Header1': text,
'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr'}
b'X-Header2': 'value',
'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr',
'X-Object-Meta-Header-not-encoded': text,
b'X-Object-Meta-Header-encoded': 'value'}

resp = MockHttpResponse()
conn[1].getresponse = resp.fake_response
Expand All @@ -757,6 +770,11 @@ def test_unicode_ok(self):
# Test unicode header
self.assertIn(('x-header1', text.encode('utf8')),
resp.buffer)
self.assertIn((b'x-object-meta-header-not-encoded',
text.encode('utf8')), resp.buffer)
self.assertIn((b'x-object-meta-header-encoded', b'value'),
resp.buffer)
self.assertIn((b'x-header2', b'value'), resp.buffer)

def test_server_error(self):
body = 'c' * 60
Expand Down

0 comments on commit 258420f

Please sign in to comment.