Skip to content

Commit

Permalink
parameters: add option to specify custom containers (refs #16)
Browse files Browse the repository at this point in the history
  • Loading branch information
swistakm committed Jul 20, 2016
1 parent 5c3f6dd commit a69d4eb
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/graceful/parameters.py
Expand Up @@ -39,7 +39,7 @@ class BaseParam():
``ValueError`` as having required parameters with default
value has no sense.
param (str): set to ``True`` if multiple occurences of this parameter
many (str): set to ``True`` if multiple occurences of this parameter
can be included in query string, as a result values for this
parameter will be always included as a list in params dict. Defaults
to ``False``.
Expand Down Expand Up @@ -70,6 +70,8 @@ def value(self, data):
spec = None
type = None

container = list

def __init__(
self,
details,
Expand Down
9 changes: 4 additions & 5 deletions src/graceful/resources/base.py
Expand Up @@ -243,11 +243,10 @@ def require_params(self, req):
try:
if param.many:
# params with "many" enabled need special care
params[name] = req.get_param_as_list(
name, param.value,
) or [
param.default and param.value(param.default)
]
params[name] = param.container(
req.get_param_as_list(name, param.value) or
[param.default and param.value(param.default)]
)
else:
# note that if many==False and query parameter
# occurs multiple times in qs then it is
Expand Down
34 changes: 34 additions & 0 deletions tests/test_resources.py
Expand Up @@ -269,6 +269,40 @@ class SomeResource(Resource):
assert 'foo' not in params


def test_parameter_with_many_and_custom_container_type_object():
class StringSetParam(StringParam):
# container is simply a type object (it is not a descriptor)
# so does not receive self as a parameter
container = set

class SomeResource(Resource):
foo = StringSetParam(details="give me foo", many=True)

env = create_environ(query_string="foo=bar&foo=baz")
resource = SomeResource()
params = resource.require_params(Request(env))

assert isinstance(params['foo'], set)
assert 'bar' in params['foo'] and 'baz' in params['foo']


def test_parameter_with_many_and_custom_container_method():
class StringSetParam(StringParam):
# container is custom method call ("bound" to param instance)
def container(self, values):
return set(values)

class SomeResource(Resource):
foo = StringSetParam(details="give me foo", many=True)

env = create_environ(query_string="foo=bar&foo=baz")
resource = SomeResource()
params = resource.require_params(Request(env))

assert isinstance(params['foo'], set)
assert 'bar' in params['foo'] and 'baz' in params['foo']


def test_parameter_value_errors_translated_to_http_errors(req, resp):
class InvalidParam(BaseParam):
def value(self, raw_value):
Expand Down

0 comments on commit a69d4eb

Please sign in to comment.