Now using type from discovery document to properly cast method parameters. Also added in checking for values that are enums.

This commit is contained in:
Joe Gregorio
2011-02-22 10:00:19 -05:00
parent 0fb19e1b01
commit bee8683681
4 changed files with 3139 additions and 366 deletions

View File

@@ -172,6 +172,31 @@ def build_from_document(
return resource
def _to_string(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
JSON Schema.
Args:
value: any, the value to convert
schema_type: string, the type that value should be interpreted as
Returns:
A string representation of 'value' based on the schema_type.
"""
if schema_type == 'string':
return str(value)
elif schema_type == 'integer':
return str(int(value))
elif schema_type == 'number':
return str(float(value))
elif schema_type == 'boolean':
return str(bool(value)).lower()
else:
return str(value)
def createResource(http, baseUrl, model, requestBuilder,
developerKey, resourceDesc, futureDesc):
@@ -203,6 +228,8 @@ def createResource(http, baseUrl, model, requestBuilder,
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
param_type = {} # The type of the parameter
enum_params = {}
if 'parameters' in methodDesc:
for arg, desc in methodDesc['parameters'].iteritems():
param = key2param(arg)
@@ -210,12 +237,15 @@ def createResource(http, baseUrl, model, requestBuilder,
if desc.get('pattern', ''):
pattern_params[param] = desc['pattern']
if desc.get('enum', ''):
enum_params[param] = desc['enum']
if desc.get('required', False):
required_params.append(param)
if desc.get('restParameterType') == 'query':
query_params.append(param)
if desc.get('restParameterType') == 'path':
path_params[param] = param
param_type[param] = desc.get('type', 'string')
for match in URITEMPLATE.finditer(pathUrl):
for namematch in VARNAME.finditer(match.group(0)):
@@ -240,13 +270,20 @@ def createResource(http, baseUrl, model, requestBuilder,
'Parameter "%s" value "%s" does not match the pattern "%s"' %
(name, kwargs[name], regex))
for name, enums in enum_params.iteritems():
if name in kwargs:
if kwargs[name] not in enums:
raise TypeError(
'Parameter "%s" value "%s" is not in the list of allowed values "%s"' %
(name, kwargs[name], str(enums)))
actual_query_params = {}
actual_path_params = {}
for key, value in kwargs.iteritems():
if key in query_params:
actual_query_params[argmap[key]] = value
actual_query_params[argmap[key]] = _to_string(value, param_type[key])
if key in path_params:
actual_path_params[argmap[key]] = value
actual_path_params[argmap[key]] = _to_string(value, param_type[key])
body_value = kwargs.get('body', None)
if self._developerKey:

File diff suppressed because it is too large Load Diff

View File

@@ -11,9 +11,53 @@
"httpMethod": "GET",
"parameters": {
"q": {
"type": "string",
"restParameterType": "query",
"required": false,
"repeated": false
},
"i": {
"type": "integer",
"restParameterType": "query",
"required": false,
"repeated": false,
"minimum": "0",
"maximum": "4294967295",
"default": "20"
},
"n": {
"type": "number",
"restParameterType": "query",
"required": false,
"repeated": false
},
"b": {
"type": "boolean",
"restParameterType": "query",
"required": false,
"repeated": false
},
"a": {
"type": "any",
"restParameterType": "query",
"required": false,
"repeated": false
},
"o": {
"type": "object",
"restParameterType": "query",
"required": false,
"repeated": false
},
"e": {
"type": "string",
"restParameterType": "query",
"required": false,
"repeated": false,
"enum": [
"foo",
"bar"
]
}
}
}

View File

@@ -62,17 +62,17 @@ class Discovery(unittest.TestCase):
# Parameter doesn't match regex
try:
buzz.activities().list(scope='@self', userId='')
buzz.activities().list(scope='@myself', userId='me')
self.fail()
except TypeError, e:
self.assertTrue('does not match' in str(e))
self.assertTrue('not in the list' in str(e))
# Parameter doesn't match regex
try:
buzz.activities().list(scope='not@', userId='foo')
self.fail()
except TypeError, e:
self.assertTrue('does not match' in str(e))
self.assertTrue('not in the list' in str(e))
# Unexpected parameter
try:
@@ -81,11 +81,32 @@ class Discovery(unittest.TestCase):
except TypeError, e:
self.assertTrue('unexpected' in str(e))
def _check_query_types(self, request):
parsed = urlparse.urlparse(request.uri)
q = parse_qs(parsed[4])
self.assertEqual(q['q'], ['foo'])
self.assertEqual(q['i'], ['1'])
self.assertEqual(q['n'], ['1.0'])
self.assertEqual(q['b'], ['false'])
self.assertEqual(q['a'], ['[1, 2, 3]'])
self.assertEqual(q['o'], ['{\'a\': 1}'])
self.assertEqual(q['e'], ['bar'])
def test_type_coercion(self):
self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
zoo = build('zoo', 'v1', self.http)
request = zoo.query(q="foo", i=1.0, n=1.0, b=0, a=[1,2,3], o={'a':1}, e='bar')
self._check_query_types(request)
request = zoo.query(q="foo", i=1, n=1, b=False, a=[1,2,3], o={'a':1}, e='bar')
self._check_query_types(request)
request = zoo.query(q="foo", i="1", n="1", b="", a=[1,2,3], o={'a':1}, e='bar')
self._check_query_types(request)
def test_buzz_resources(self):
self.http = HttpMock(datafile('buzz.json'), {'status': '200'})
buzz = build('buzz', 'v1', self.http)
self.assertTrue(getattr(buzz, 'activities'))
self.assertTrue(getattr(buzz, 'feeds'))
self.assertTrue(getattr(buzz, 'photos'))
self.assertTrue(getattr(buzz, 'people'))
self.assertTrue(getattr(buzz, 'groups'))