Reputation: 662
I have functions, that return validator functions, simple example:
def check_len(n):
return lambda s: len(s) == n
Is it possible to add a decorator, that prints out a message, in case the check evaluates to false? Something like this:
@log_false_but_how
def check_len(n):
return lambda s: len(s) == n
check_one = check_len(1)
print(check_one('a')) # returns True
print(check_one('abc')) # return False
Expected output:
True
validator evaluated to False
False
I've tried creating an annotation, but can only access the function creation with it. One way would be to define the functions like this:
def log_false(fn):
def inner(*args):
res = fn(*args)
if not res:
print("validation failed for {}".format(fn.__name__))
return res
return inner
@log_false
def check_one(s):
return check_len(1)(s)
But this way we lose the dynamic creation of validation functions.
Upvotes: 4
Views: 209
Reputation: 43246
You're doing the validation in the wrong place. check_len
is a function factory, so res
is not a boolean - it's a function. Your @log_false
decorator has to wrap a validator function around each lambda returned by check_len
. Basically you need to write a decorator that decorates the returned functions.
def log_false(validator_factory):
# We'll create a wrapper for the validator_factory
# that applies a decorator to each function returned
# by the factory
def check_result(validator):
@functools.wraps(validator)
def wrapper(*args, **kwargs):
result = validator(*args, **kwargs)
if not result:
name = validator_factory.__name__
print('validation failed for {}'.format(name))
return result
return wrapper
@functools.wraps(validator_factory)
def wrapper(*args, **kwargs):
validator = validator_factory(*args, **kwargs)
return check_result(validator)
return wrapper
Result:
@log_false
def check_len(n):
return lambda s: len(s) == n
check_one = check_len(1)
print(check_one('a')) # prints nothing
print(check_one('abc')) # prints "validation failed for check_len"
Upvotes: 3