From 61d7e96dcd79ca9749925b67aedc09e0971e3afc Mon Sep 17 00:00:00 2001 From: Joe Gregorio Date: Tue, 22 Feb 2011 22:52:07 -0500 Subject: [PATCH] Added support for repeating parameters --- apiclient/discovery.py | 30 +++++++++++++++++++++--------- apiclient/model.py | 11 ++++++++--- samples/translate/main.py | 10 +++++----- tests/test_json_model.py | 8 ++++++-- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/apiclient/discovery.py b/apiclient/discovery.py index b202913..dbaac08 100644 --- a/apiclient/discovery.py +++ b/apiclient/discovery.py @@ -177,7 +177,7 @@ def build_from_document( return resource -def _to_string(value, schema_type): +def _cast(value, schema_type): """Convert value to a string based on JSON Schema type. See http://tools.ietf.org/html/draft-zyp-json-schema-03 for more details on @@ -237,6 +237,7 @@ def createResource(http, baseUrl, model, requestBuilder, argmap = {} # Map from method parameter name to query parameter name required_params = [] # Required parameters + repeated_params = [] # Repeated parameters pattern_params = {} # Parameters that must match a regex query_params = [] # Parameters that will be used in the query string path_params = {} # Parameters that will be used in the base URL @@ -255,6 +256,8 @@ def createResource(http, baseUrl, model, requestBuilder, enum_params[param] = desc['enum'] if desc.get('required', False): required_params.append(param) + if desc.get('repeated', False): + repeated_params.append(param) if desc.get('restParameterType') == 'query': query_params.append(param) if desc.get('restParameterType') == 'path': @@ -294,11 +297,16 @@ def createResource(http, baseUrl, model, requestBuilder, actual_query_params = {} actual_path_params = {} for key, value in kwargs.iteritems(): - value_as_str = _to_string(value, param_type.get(key, 'string')) + to_type = param_type.get(key, 'string') + # For repeated parameters we cast each member of the list. + if key in repeated_params and type(value) == type([]): + cast_value = [_cast(x, to_type) for x in value] + else: + cast_value = _cast(value, to_type) if key in query_params: - actual_query_params[argmap[key]] = value_as_str + actual_query_params[argmap[key]] = cast_value if key in path_params: - actual_path_params[argmap[key]] = value_as_str + actual_path_params[argmap[key]] = cast_value body_value = kwargs.get('body', None) if self._developerKey: @@ -330,17 +338,21 @@ def createResource(http, baseUrl, model, requestBuilder, docs = [methodDesc.get('description', DEFAULT_METHOD_DOC), '\n\n'] if len(argmap) > 0: - docs.append("Args:\n") + docs.append('Args:\n') for arg in argmap.iterkeys(): if arg in STACK_QUERY_PARAMETERS: continue - required = "" + repeated = '' + if arg in repeated_params: + repeated = ' (repeated)' + required = '' if arg in required_params: - required = " (required)" + required = ' (required)' paramdesc = methodDesc['parameters'][argmap[arg]] paramdoc = paramdesc.get('description', 'A parameter') paramtype = paramdesc.get('type', 'string') - docs.append(' %s: %s, %s%s\n' % (arg, paramtype, paramdoc, required)) + docs.append(' %s: %s, %s%s%s\n' % (arg, paramtype, paramdoc, required, + repeated)) enum = paramdesc.get('enum', []) enumDesc = paramdesc.get('enumDescriptions', []) if enum and enumDesc: @@ -430,7 +442,7 @@ def createResource(http, baseUrl, model, requestBuilder, if futureDesc and 'methods' in futureDesc: for methodName, methodDesc in futureDesc['methods'].iteritems(): if 'next' in methodDesc and methodName in resourceDesc['methods']: - createNextMethod(Resource, methodName + "_next", + createNextMethod(Resource, methodName + '_next', resourceDesc['methods'][methodName], methodDesc['next']) diff --git a/apiclient/model.py b/apiclient/model.py index 55bcc94..14ec397 100644 --- a/apiclient/model.py +++ b/apiclient/model.py @@ -127,9 +127,14 @@ class JsonModel(Model): params.update({'alt': 'json'}) astuples = [] for key, value in params.iteritems(): - if getattr(value, 'encode', False) and callable(value.encode): - value = value.encode('utf-8') - astuples.append((key, value)) + if type(value) == type([]): + for x in value: + x = x.encode('utf-8') + astuples.append((key, x)) + else: + if getattr(value, 'encode', False) and callable(value.encode): + value = value.encode('utf-8') + astuples.append((key, value)) return '?' + urllib.urlencode(astuples) def response(self, resp, content): diff --git a/samples/translate/main.py b/samples/translate/main.py index 24f0648..ae39130 100644 --- a/samples/translate/main.py +++ b/samples/translate/main.py @@ -21,12 +21,12 @@ import pprint def main(): - p = build("translate", "v2", - developerKey="AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0") + p = build('translate', 'v2', + developerKey='AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0') print p.translations().list( - source="en", - target="fr", - q="flower" + source='en', + target='fr', + q=['flower', 'car'] ).execute() if __name__ == '__main__': diff --git a/tests/test_json_model.py b/tests/test_json_model.py index fa7ad05..88f2400 100644 --- a/tests/test_json_model.py +++ b/tests/test_json_model.py @@ -101,7 +101,9 @@ class Model(unittest.TestCase): headers = {} path_params = {} - query_params = {'foo': 1, 'bar': u'\N{COMET}'} + query_params = {'foo': 1, 'bar': u'\N{COMET}', + 'baz': ['fe', 'fi', 'fo', 'fum'], # Repeated parameters + 'qux': []} body = {} headers, params, query, body = model.request(headers, path_params, query_params, body) @@ -109,9 +111,11 @@ class Model(unittest.TestCase): self.assertEqual(headers['accept'], 'application/json') self.assertEqual(headers['content-type'], 'application/json') - query_dict = parse_qs(query) + query_dict = parse_qs(query[1:]) self.assertEqual(query_dict['foo'], ['1']) self.assertEqual(query_dict['bar'], [u'\N{COMET}'.encode('utf-8')]) + self.assertEqual(query_dict['baz'], ['fe', 'fi', 'fo', 'fum']) + self.assertTrue('qux' not in query_dict) self.assertEqual(body, '{}') def test_user_agent(self):