feat: Add ability to pass a dict 'store' to req.get_param
This patch adds an optional 'store' method argument to req.get_param and friends. This makes it easy to construct sparse dicts corresponding to query string params, e.g., for use as kwargs when calling app functions. Closes issue #130
This commit is contained in:
@@ -367,13 +367,15 @@ class Request(object):
|
||||
description = 'The "' + name + '" header is required.'
|
||||
raise HTTPBadRequest('Missing header', description)
|
||||
|
||||
def get_param(self, name, required=False):
|
||||
def get_param(self, name, required=False, store=None):
|
||||
"""Return the value of a query string parameter as a string
|
||||
|
||||
Args:
|
||||
name: Parameter name, case-sensitive (e.g., 'sort')
|
||||
required: Set to True to raise HTTPBadRequest instead of returning
|
||||
gracefully when the parameter is not found (default False)
|
||||
store: A dict-like object in which to place the value of the
|
||||
param, but only if the param is found.
|
||||
|
||||
Returns:
|
||||
The value of the param as a string, or None if param is not found
|
||||
@@ -388,6 +390,9 @@ class Request(object):
|
||||
# PERF: Use if..in since it is a good all-around performer; we don't
|
||||
# know how likely params are to be specified by clients.
|
||||
if name in self._params:
|
||||
if store is not None:
|
||||
store[name] = self._params[name]
|
||||
|
||||
return self._params[name]
|
||||
|
||||
if not required:
|
||||
@@ -396,7 +401,8 @@ class Request(object):
|
||||
description = 'The "' + name + '" query parameter is required.'
|
||||
raise HTTPBadRequest('Missing query parameter', description)
|
||||
|
||||
def get_param_as_int(self, name, required=False, min=None, max=None):
|
||||
def get_param_as_int(self, name,
|
||||
required=False, min=None, max=None, store=None):
|
||||
"""Return the value of a query string parameter as an int
|
||||
|
||||
Args:
|
||||
@@ -409,6 +415,8 @@ class Request(object):
|
||||
max: Set to the maximum value allowed for this param. If the param
|
||||
is found and its value is greater than max, an HTTPError is
|
||||
raised.
|
||||
store: A dict-like object in which to place the value of the
|
||||
param, but only if the param is found (default None)
|
||||
|
||||
Returns:
|
||||
The value of the param if it is found and can be converted to an
|
||||
@@ -444,6 +452,9 @@ class Request(object):
|
||||
'parameter may not exceed %d') % max
|
||||
raise InvalidHeaderValueError(description)
|
||||
|
||||
if store is not None:
|
||||
store[name] = val
|
||||
|
||||
return val
|
||||
|
||||
if not required:
|
||||
@@ -452,7 +463,7 @@ class Request(object):
|
||||
description = 'The "' + name + '" query parameter is required.'
|
||||
raise HTTPBadRequest('Missing query parameter', description)
|
||||
|
||||
def get_param_as_bool(self, name, required=False):
|
||||
def get_param_as_bool(self, name, required=False, store=None):
|
||||
"""Return the value of a query string parameter as a boolean
|
||||
|
||||
Args:
|
||||
@@ -460,6 +471,8 @@ class Request(object):
|
||||
required: Set to True to raise HTTPBadRequest instead of returning
|
||||
gracefully when the parameter is not found or is not one of
|
||||
['true', 'false'] (default False)
|
||||
store: A dict-like object in which to place the value of the
|
||||
param, but only if the param is found (default None)
|
||||
|
||||
Returns:
|
||||
The value of the param if it is found and can be converted to a
|
||||
@@ -477,21 +490,27 @@ class Request(object):
|
||||
if name in self._params:
|
||||
val = self._params[name]
|
||||
if val == 'true':
|
||||
return True
|
||||
val = True
|
||||
elif val == 'false':
|
||||
return False
|
||||
val = False
|
||||
else:
|
||||
description = ('The value of the "' + name + '" query '
|
||||
'parameter must be "true" or "false".')
|
||||
raise InvalidParamValueError(description)
|
||||
|
||||
if store is not None:
|
||||
store[name] = val
|
||||
|
||||
return val
|
||||
|
||||
if not required:
|
||||
return None
|
||||
|
||||
description = 'The "' + name + '" query parameter is required.'
|
||||
raise HTTPBadRequest('Missing query parameter', description)
|
||||
|
||||
def get_param_as_list(self, name, transform=None, required=False):
|
||||
def get_param_as_list(self, name,
|
||||
transform=None, required=False, store=None):
|
||||
"""Return the value of a query string parameter as a list
|
||||
|
||||
Note that list items must be comma-separated.
|
||||
@@ -504,6 +523,8 @@ class Request(object):
|
||||
required: Set to True to raise HTTPBadRequest instead of returning
|
||||
gracefully when the parameter is not found or is not an
|
||||
integer (default False)
|
||||
store: A dict-like object in which to place the value of the
|
||||
param, but only if the param is found (default None)
|
||||
|
||||
Returns:
|
||||
The value of the param if it is found. Otherwise, returns None
|
||||
@@ -527,6 +548,9 @@ class Request(object):
|
||||
'is not formatted correctly.')
|
||||
raise InvalidParamValueError(desc)
|
||||
|
||||
if store is not None:
|
||||
store[name] = items
|
||||
|
||||
return items
|
||||
|
||||
if not required:
|
||||
|
||||
@@ -13,8 +13,10 @@ class TestQueryParams(testing.TestBase):
|
||||
self.simulate_request('/', query_string=query_string)
|
||||
|
||||
req = self.resource.req
|
||||
store = {}
|
||||
self.assertIs(req.get_param('marker'), None)
|
||||
self.assertIs(req.get_param('limit'), None)
|
||||
self.assertIs(req.get_param('limit', store), None)
|
||||
self.assertNotIn('limit', store)
|
||||
self.assertIs(req.get_param_as_int('limit'), None)
|
||||
self.assertIs(req.get_param_as_bool('limit'), None)
|
||||
self.assertIs(req.get_param_as_list('limit'), None)
|
||||
@@ -26,13 +28,22 @@ class TestQueryParams(testing.TestBase):
|
||||
req = self.resource.req
|
||||
self.assertIs(req.get_param('marker'), None)
|
||||
|
||||
store = {}
|
||||
self.assertIs(req.get_param('marker', store=store), None)
|
||||
self.assertNotIn('marker', store)
|
||||
|
||||
def test_simple(self):
|
||||
query_string = 'marker=deadbeef&limit=25'
|
||||
self.simulate_request('/', query_string=query_string)
|
||||
|
||||
req = self.resource.req
|
||||
self.assertEquals(req.get_param('marker') or 'deadbeef', 'deadbeef')
|
||||
self.assertEquals(req.get_param('limit') or '25', '25')
|
||||
store = {}
|
||||
self.assertEquals(req.get_param('marker', store=store) or 'nada',
|
||||
'deadbeef')
|
||||
self.assertEquals(req.get_param('limit', store=store) or '0', '25')
|
||||
|
||||
self.assertEquals(store['marker'], 'deadbeef')
|
||||
self.assertEquals(store['limit'], '25')
|
||||
|
||||
def test_allowed_names(self):
|
||||
query_string = ('p=0&p1=23&2p=foo&some-thing=that&blank=&some_thing=x&'
|
||||
@@ -69,8 +80,13 @@ class TestQueryParams(testing.TestBase):
|
||||
req = self.resource.req
|
||||
self.assertRaises(falcon.HTTPBadRequest, req.get_param_as_int,
|
||||
'marker')
|
||||
|
||||
self.assertEquals(req.get_param_as_int('limit'), 25)
|
||||
|
||||
store = {}
|
||||
self.assertEquals(req.get_param_as_int('limit', store=store), 25)
|
||||
self.assertEquals(store['limit'], 25)
|
||||
|
||||
self.assertEquals(
|
||||
req.get_param_as_int('limit', min=1, max=50), 25)
|
||||
|
||||
@@ -153,6 +169,10 @@ class TestQueryParams(testing.TestBase):
|
||||
self.assertEquals(req.get_param_as_bool('echo'), True)
|
||||
self.assertEquals(req.get_param_as_bool('doit'), False)
|
||||
|
||||
store = {}
|
||||
self.assertEquals(req.get_param_as_bool('echo', store=store), True)
|
||||
self.assertEquals(store['echo'], True)
|
||||
|
||||
def test_list_type(self):
|
||||
query_string = 'colors=red,green,blue&limit=1'
|
||||
self.simulate_request('/', query_string=query_string)
|
||||
@@ -164,6 +184,10 @@ class TestQueryParams(testing.TestBase):
|
||||
self.assertEquals(req.get_param_as_list('limit'), ['1'])
|
||||
self.assertIs(req.get_param_as_list('marker'), None)
|
||||
|
||||
store = {}
|
||||
self.assertEquals(req.get_param_as_list('limit', store=store), ['1'])
|
||||
self.assertEquals(store['limit'], ['1'])
|
||||
|
||||
def test_list_transformer(self):
|
||||
query_string = 'coord=1.4,13,15.1&limit=100'
|
||||
self.simulate_request('/', query_string=query_string)
|
||||
|
||||
Reference in New Issue
Block a user