summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2016-08-23 16:17:21 -0700
committerTim Burke <tim.burke@gmail.com>2016-11-18 11:47:14 -0800
commita1e2bcde4a54a33054c7dcb31c3c3b0e6d72d021 (patch)
tree46a4d7b28a5c2ac4a317c7f2abede8159772510d
parent12d42efad23f95461692af99a77136d7591a5fee (diff)
downloadpython-swiftclient-a1e2bcde4a54a33054c7dcb31c3c3b0e6d72d021.tar.gz
Accept more types of input for headers/meta
Previously, we only accepted iterables of strings like 'Header: Value'. Now, we'll also accept lists of tuples like ('Header', 'Value') as well as dictionaries like {'Header': 'Value'}. This should be more intuitive for application developers, who are already used to being able to pass dicts or lists of tuples to libraries like requests. Change-Id: I93ed2f1e8305f0168b7a4bd90c205b04730da836
-rw-r--r--swiftclient/service.py8
-rw-r--r--swiftclient/utils.py22
-rw-r--r--tests/unit/test_service.py19
3 files changed, 37 insertions, 12 deletions
diff --git a/swiftclient/service.py b/swiftclient/service.py
index de30d50..8c6880a 100644
--- a/swiftclient/service.py
+++ b/swiftclient/service.py
@@ -29,11 +29,10 @@ from posixpath import join as urljoin
from random import shuffle
from time import time
from threading import Thread
-from six import StringIO, text_type
+from six import Iterator, StringIO, string_types, text_type
from six.moves.queue import Queue
from six.moves.queue import Empty as QueueEmpty
from six.moves.urllib.parse import quote
-from six import Iterator, string_types
import json
@@ -274,7 +273,10 @@ def split_headers(options, prefix=''):
"""
Splits 'Key: Value' strings and returns them as a dictionary.
- :param options: An array of 'Key: Value' strings
+ :param options: Must be one of:
+ * an iterable of 'Key: Value' strings
+ * an iterable of ('Key', 'Value') pairs
+ * a dict of {'Key': 'Value'} pairs
:param prefix: String to prepend to all of the keys in the dictionary.
reporting.
"""
diff --git a/swiftclient/utils.py b/swiftclient/utils.py
index e14602d..aa8b28a 100644
--- a/swiftclient/utils.py
+++ b/swiftclient/utils.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Miscellaneous utility functions for use with Swift."""
+import collections
import gzip
import hashlib
import hmac
@@ -148,15 +149,24 @@ def parse_api_response(headers, body):
def split_request_headers(options, prefix=''):
headers = {}
+ if isinstance(options, collections.Mapping):
+ options = options.items()
for item in options:
- split_item = item.split(':', 1)
- if len(split_item) == 2:
- headers[(prefix + split_item[0]).title()] = split_item[1].strip()
- else:
+ if isinstance(item, six.string_types):
+ if ':' not in item:
+ raise ValueError(
+ "Metadata parameter %s must contain a ':'.\n"
+ "Example: 'Color:Blue' or 'Size:Large'"
+ % item
+ )
+ item = item.split(':', 1)
+ if len(item) != 2:
raise ValueError(
- "Metadata parameter %s must contain a ':'.\n%s"
- % (item, "Example: 'Color:Blue' or 'Size:Large'")
+ "Metadata parameter %r must have exactly two items.\n"
+ "Example: ('Color', 'Blue') or ['Size', 'Large']"
+ % (item, )
)
+ headers[(prefix + item[0]).title()] = item[1].strip()
return headers
diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py
index e8385b7..2fc827c 100644
--- a/tests/unit/test_service.py
+++ b/tests/unit/test_service.py
@@ -592,11 +592,24 @@ class TestServiceUtils(unittest.TestCase):
actual = swiftclient.service.split_headers(mock_headers, 'prefix-')
self.assertEqual(expected, actual)
- def test_split_headers_error(self):
- mock_headers = ['notvalid']
+ def test_split_headers_list_of_tuples(self):
+ mock_headers = [('color', 'blue'), ('size', 'large')]
+ expected = {'Prefix-Color': 'blue', 'Prefix-Size': 'large'}
+
+ actual = swiftclient.service.split_headers(mock_headers, 'prefix-')
+ self.assertEqual(expected, actual)
+ def test_split_headers_dict(self):
+ expected = {'Color': 'blue', 'Size': 'large'}
+
+ actual = swiftclient.service.split_headers(expected)
+ self.assertEqual(expected, actual)
+
+ def test_split_headers_error(self):
+ self.assertRaises(SwiftError, swiftclient.service.split_headers,
+ ['notvalid'])
self.assertRaises(SwiftError, swiftclient.service.split_headers,
- mock_headers)
+ [('also', 'not', 'valid')])
class TestSwiftUploadObject(unittest.TestCase):