From 307ea6c9eb9ed3d7ebbdc7d885dfb1a971a2be48 Mon Sep 17 00:00:00 2001 From: Alfredo Deza Date: Thu, 18 Dec 2014 15:18:42 -0600 Subject: [PATCH] re-purpose urlencode to craft the query string for us without quoting again Signed-off-by: Alfredo Deza --- radosgw_agent/request.py | 71 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/radosgw_agent/request.py b/radosgw_agent/request.py index 56c45ff..86cc066 100644 --- a/radosgw_agent/request.py +++ b/radosgw_agent/request.py @@ -1,11 +1,80 @@ import boto import logging +import sys from boto.connection import AWSAuthConnection -from urllib import urlencode log = logging.getLogger(__name__) +def urlencode(query, doseq=0): + """ + Note: ported from urllib.urlencode, but with the ability to craft the query + string without quoting the params again. + + Encode a sequence of two-element tuples or dictionary into a URL query + string. + + If any values in the query arg are sequences and doseq is true, each + sequence element is converted to a separate parameter. + + If the query arg is a sequence of two-element tuples, the order of the + parameters in the output will match the order of parameters in the + input. + """ + + if hasattr(query, "items"): + # mapping objects + query = query.items() + else: + # it's a bother at times that strings and string-like objects are + # sequences... + try: + # non-sequence items should not work with len() + # non-empty strings will fail this + if len(query) and not isinstance(query[0], tuple): + raise TypeError + # zero-length sequences of all types will get here and succeed, + # but that's a minor nit - since the original implementation + # allowed empty dicts that type of behavior probably should be + # preserved for consistency + except TypeError: + ty, va, tb = sys.exc_info() + raise TypeError, "not a valid non-string sequence or mapping object", tb + + l = [] + if not doseq: + # preserve old behavior + for k, v in query: + k = str(k) + v = str(v) + l.append(k + '=' + v) + print l + else: + for k, v in query: + k = str(k) + if isinstance(v, str): + l.append(k + '=' + v) + elif isinstance(v, unicode): + # is there a reasonable way to convert to ASCII? + # encode generates a string, but "replace" or "ignore" + # lose information and "strict" can raise UnicodeError + v = v.encode("ASCII", "replace") + l.append(k + '=' + v) + else: + try: + # is this a sufficient test for sequence-ness? + len(v) + except TypeError: + # not a sequence + v = str(v) + l.append(k + '=' + v) + else: + # loop over the sequence + for elt in v: + l.append(k + '=' + str(elt)) + return '&'.join(l) + + class MetaData(object): """ A basic container class that other than the method, it just registers -- 2.47.3