def apply_(*args, **kwargs):
"""
Decorator for per-view rules applying
Usage:
@apply_('rule1', 'rule2', 'rule3', default_context={'key': 'foo'})
def some_view(request, arg1, arg2):
pass
"""
rules = []
for arg in args:
if isinstance(arg, (list, tuple)):
rules += list(arg)
elif isinstance(arg, str):
rules += [arg]
else:
raise ValueError("Wrong arg %s for apply_" % (arg,))
default_context = None
if kwargs:
if kwargs.keys() != ['default_context']:
raise ValueError('Only default_context is allowed keyword argument')
else:
default_context = kwargs['default_context']
def checker(view_func):
def wrapper(*args, **kwargs):
if default_context is not None:
extra = default_context
else:
extra = {}
extra['caller'] = view_func.__name__
keys = getargspec(view_func).args
for i, key in enumerate(keys):
try:
extra[key] = args[i]
except IndexError:
extra[key] = kwargs[key]
if 'city' not in extra:
raise ValueError('Each rule requires city in args')
city = extra['city']
for rule_name in rules:
rule = RULES[rule_name]
ok, reason = rule(city, extra)
if not ok:
return HttpResponse(unicode(reason),
mimetype='text/plain',
status=404)
return view_func(*args, **kwargs)
view_func._applied_rules = rules
return wraps(view_func)(wrapper)
return checker