mirror of https://github.com/zulip/zulip.git
Add validator support to REQ and has_request_variables.
Validators are similar to converters, but they don't have to parse JSON, and they are told the name of the request variable to help format error messages. (imported from commit 3c33e301892519c67e70675006d5686d9f013353)
This commit is contained in:
parent
60917c83d6
commit
bfb54b5a4d
|
@ -332,7 +332,7 @@ class REQ(object):
|
||||||
pass
|
pass
|
||||||
NotSpecified = _NotSpecified()
|
NotSpecified = _NotSpecified()
|
||||||
|
|
||||||
def __init__(self, whence=None, converter=None, default=NotSpecified):
|
def __init__(self, whence=None, converter=None, default=NotSpecified, validator=None):
|
||||||
"""
|
"""
|
||||||
whence: the name of the request variable that should be used
|
whence: the name of the request variable that should be used
|
||||||
for this parameter. Defaults to a request variable of the
|
for this parameter. Defaults to a request variable of the
|
||||||
|
@ -344,13 +344,21 @@ class REQ(object):
|
||||||
|
|
||||||
default: a value to be used for the argument if the parameter
|
default: a value to be used for the argument if the parameter
|
||||||
is missing in the request
|
is missing in the request
|
||||||
|
|
||||||
|
validator: similar to converter, but takes an already parsed JSON
|
||||||
|
data structure. If specified, we will parse the JSON request
|
||||||
|
variable value before passing to the function
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.post_var_name = whence
|
self.post_var_name = whence
|
||||||
self.func_var_name = None
|
self.func_var_name = None
|
||||||
self.converter = converter
|
self.converter = converter
|
||||||
|
self.validator = validator
|
||||||
self.default = default
|
self.default = default
|
||||||
|
|
||||||
|
if converter and validator:
|
||||||
|
raise Exception('converter and validator are mutually exclusive')
|
||||||
|
|
||||||
# Extracts variables from the request object and passes them as
|
# Extracts variables from the request object and passes them as
|
||||||
# named function arguments. The request object must be the first
|
# named function arguments. The request object must be the first
|
||||||
# argument to the function.
|
# argument to the function.
|
||||||
|
@ -414,6 +422,18 @@ def has_request_variables(view_func):
|
||||||
val = param.converter(val)
|
val = param.converter(val)
|
||||||
except:
|
except:
|
||||||
raise RequestVariableConversionError(param.post_var_name, val)
|
raise RequestVariableConversionError(param.post_var_name, val)
|
||||||
|
|
||||||
|
# Validators are like converters, but they don't handle JSON parsing; we do.
|
||||||
|
if param.validator is not None and not default_assigned:
|
||||||
|
try:
|
||||||
|
val = ujson.loads(val)
|
||||||
|
except:
|
||||||
|
raise JsonableError('argument "%s" is not valid json.' % (param.post_var_name,))
|
||||||
|
|
||||||
|
error = param.validator(param.post_var_name, val)
|
||||||
|
if error:
|
||||||
|
raise JsonableError(error)
|
||||||
|
|
||||||
kwargs[param.func_var_name] = val
|
kwargs[param.func_var_name] = val
|
||||||
|
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
|
@ -226,6 +226,35 @@ class DecoratorTestCase(TestCase):
|
||||||
result = get_total(request)
|
result = get_total(request)
|
||||||
self.assertEqual(result, 21)
|
self.assertEqual(result, 21)
|
||||||
|
|
||||||
|
def test_REQ_validator(self):
|
||||||
|
|
||||||
|
@has_request_variables
|
||||||
|
def get_total(request, numbers=REQ(validator=check_list(check_int))):
|
||||||
|
return sum(numbers)
|
||||||
|
|
||||||
|
class Request:
|
||||||
|
pass
|
||||||
|
|
||||||
|
request = Request()
|
||||||
|
request.REQUEST = {}
|
||||||
|
|
||||||
|
with self.assertRaises(RequestVariableMissingError):
|
||||||
|
get_total(request)
|
||||||
|
|
||||||
|
request.REQUEST['numbers'] = 'bad_value'
|
||||||
|
with self.assertRaises(JsonableError) as cm:
|
||||||
|
get_total(request)
|
||||||
|
self.assertEqual(str(cm.exception), 'argument "numbers" is not valid json.')
|
||||||
|
|
||||||
|
request.REQUEST['numbers'] = ujson.dumps([1,2,"what?",4,5,6])
|
||||||
|
with self.assertRaises(JsonableError) as cm:
|
||||||
|
get_total(request)
|
||||||
|
self.assertEqual(str(cm.exception), 'numbers[2] is not an integer')
|
||||||
|
|
||||||
|
request.REQUEST['numbers'] = ujson.dumps([1,2,3,4,5,6])
|
||||||
|
result = get_total(request)
|
||||||
|
self.assertEqual(result, 21)
|
||||||
|
|
||||||
class ValidatorTestCase(TestCase):
|
class ValidatorTestCase(TestCase):
|
||||||
def test_check_string(self):
|
def test_check_string(self):
|
||||||
x = "hello"
|
x = "hello"
|
||||||
|
|
Loading…
Reference in New Issue