Added support for URLs with many parameters e.g. max-liked, max-results and max-comments. I'm not checking in the functional tests I'm using since I still haven't fixed the problem of getting back a usable list of JSON objects for pagination.
diff --git a/apiclient/discovery.py b/apiclient/discovery.py
index 93133a8..3cd2c9f 100644
--- a/apiclient/discovery.py
+++ b/apiclient/discovery.py
@@ -22,6 +22,7 @@
import httplib2
+import logging
import re
import simplejson
import urlparse
@@ -77,17 +78,21 @@
class JsonModel(object):
- def request(self, headers, params):
- model = params.get('body', None)
- query = '?alt=json&prettyprint=true'
+ def request(self, headers, path_params, query_params, body_value):
+ query = self.build_query(query_params)
headers['accept'] = 'application/json'
- if model == None:
- return (headers, params, query, None)
+ if body_value is None:
+ return (headers, path_params, query, None)
else:
- model = {'data': model}
+ model = {'data': body_value}
headers['content-type'] = 'application/json'
- del params['body']
- return (headers, params, query, simplejson.dumps(model))
+ return (headers, path_params, query, simplejson.dumps(model))
+
+ def build_query(self, params):
+ query = '?alt=json&prettyprint=true'
+ for key,value in params.iteritems():
+ query += '&%s=%s' % (key, value)
+ return query
def response(self, resp, content):
# Error handling is TBD, for example, do we retry
@@ -95,6 +100,7 @@
if resp.status < 300:
return simplejson.loads(content)['data']
else:
+ logging.debug('Content from bad request was: %s' % content)
if resp['content-type'] != 'application/json':
raise HttpError('%d %s' % (resp.status, resp.reason))
else:
@@ -107,7 +113,10 @@
'api': service,
'apiVersion': version
}
- resp, content = http.request(uritemplate.expand(discoveryServiceUrl, params))
+
+ requested_url = uritemplate.expand(discoveryServiceUrl, params)
+ logging.info('URL being requested: %s' % requested_url)
+ resp, content = http.request(requested_url)
d = simplejson.loads(content)
service = d['data'][service][version]
base = service['baseUrl']
@@ -149,45 +158,59 @@
pathUrl = methodDesc['pathUrl']
pathUrl = re.sub(r'\{', r'{+', pathUrl)
httpMethod = methodDesc['httpMethod']
- args = methodDesc['parameters'].keys()
- required = [] # Required parameters
- pattern = {} # Parameters the must match a regex
+ argmap = {}
+ if httpMethod in ['PUT', 'POST']:
+ argmap['body'] = 'body'
+
+
+ required_params = [] # Required 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
for arg, desc in methodDesc['parameters'].iteritems():
param = key2param(arg)
- if desc.get('pattern', ''):
- pattern[param] = desc['pattern']
- if desc.get('required', False):
- required.append(param)
+ argmap[param] = arg
- if httpMethod in ['PUT', 'POST']:
- args.append('body')
- argmap = dict([(key2param(key), key) for key in args])
+ if desc.get('pattern', ''):
+ pattern_params[param] = desc['pattern']
+ if desc.get('required', False):
+ required_params.append(param)
+ if desc.get('parameterType') == 'query':
+ query_params.append(param)
+ if desc.get('parameterType') == 'path':
+ path_params[param]=param
def method(self, **kwargs):
for name in kwargs.iterkeys():
if name not in argmap:
raise TypeError('Got an unexpected keyword argument "%s"' % name)
- for name in required:
+ for name in required_params:
if name not in kwargs:
raise TypeError('Missing required parameter "%s"' % name)
- for name, regex in pattern.iteritems():
+ for name, regex in pattern_params.iteritems():
if name in kwargs:
if re.match(regex, kwargs[name]) is None:
raise TypeError('Parameter "%s" value "%s" does not match the pattern "%s"' % (name, kwargs[name], regex))
- params = {}
+ actual_query_params = {}
+ actual_path_params = {}
for key, value in kwargs.iteritems():
- params[argmap[key]] = value
+ if key in query_params:
+ actual_query_params[argmap[key]] = value
+ if key in path_params:
+ actual_path_params[argmap[key]] = value
+ body_value = kwargs.get('body', None)
headers = {}
- headers, params, query, body = self._model.request(headers, params)
+ headers, params, query, body = self._model.request(headers, actual_path_params, actual_query_params, body_value)
- url = urlparse.urljoin(self._baseUrl,
- uritemplate.expand(pathUrl, params) + query)
+ expanded_url = uritemplate.expand(pathUrl, params)
+ url = urlparse.urljoin(self._baseUrl, expanded_url + query)
+ logging.info('URL being requested: %s' % url)
resp, content = self._http.request(
url, method=httpMethod, headers=headers, body=body)
diff --git a/tests/test_discovery.py b/tests/test_discovery.py
index a217932..6af7d0b 100644
--- a/tests/test_discovery.py
+++ b/tests/test_discovery.py
@@ -61,7 +61,7 @@
except TypeError, e:
self.assertTrue('unexpected' in str(e))
- def test_resources(self):
+ def test_buzz_resources(self):
self.http = HttpMock('buzz.json', {'status': '200'})
buzz = build('buzz', 'v1', self.http)
self.assertTrue(getattr(buzz, 'activities'))
diff --git a/tests/test_json_model.py b/tests/test_json_model.py
index 477f88d..7b95d58 100644
--- a/tests/test_json_model.py
+++ b/tests/test_json_model.py
@@ -19,9 +19,11 @@
model = JsonModel()
headers = {}
- params = {}
+ path_params = {}
+ query_params = {}
+ body = None
- headers, params, query, body = model.request(headers, params)
+ headers, params, query, body = model.request(headers, path_params, query_params, body)
self.assertEqual(headers['accept'], 'application/json')
self.assertTrue('content-type' not in headers)
@@ -32,9 +34,11 @@
model = JsonModel()
headers = {}
- params = {'body': {}}
+ path_params = {}
+ query_params = {}
+ body = {}
- headers, params, query, body = model.request(headers, params)
+ headers, params, query, body = model.request(headers, path_params, query_params, body)
self.assertEqual(headers['accept'], 'application/json')
self.assertEqual(headers['content-type'], 'application/json')