Created
May 26, 2009 11:19
-
-
Save anfedorov/118018 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from functools import wraps | |
def predecoration(decoration=None, has_params=False): | |
"Decorates a function as a pre-decorator" | |
def metadecorator(decoration): | |
"Takes a decoration to pre-apply to a func" | |
def cap_args(*dec_args, **dec_kwds): | |
"Captures decorator arguments" | |
def decorator_with_args(func): | |
"The Decorator - takes a func to pre-decorate" | |
@wraps(func) | |
def decoration_then_func(*args, **kwds): | |
"Runs decoration, then func" | |
# the decoration will be passed its arguments along with the func arguments | |
decoration_args = {} | |
if dec_args: decoration_args['dec_args'] = dec_args | |
if dec_kwds: decoration_args['dec_kwds'] = dec_kwds | |
if args: decoration_args['args'] = args | |
if kwds: decoration_args['kwds'] = kwds | |
# run decoration, and if return value is truthy, modify arguments to func | |
decoration_return = decoration(**decoration_args) | |
if decoration_return: | |
if type(decoration_return) == tuple: | |
if len(decoration_return) == 2 and type(decoration_return[0]) == tuple and type(decoration_return[1]) == dict: | |
args = decoration_return[0] | |
kwds.update(decoration_return[1]) | |
else: | |
args = decoration_return | |
elif type(decoration_return) == dict: | |
kwds.update(decoration_return) | |
else: | |
args = (decoration_return,) | |
return func(*args, **kwds) | |
return decoration_then_func | |
return decorator_with_args | |
return cap_args | |
return metadecorator if has_params else metadecorator(decoration)((), {}) | |
# examples | |
@predecorator | |
def debug_input(*input): | |
print input | |
@debug_input | |
def foo(x,y): | |
return x+y | |
@predecorator(has_params=True) | |
def accepts(args, dec_args): | |
for (a,t) in zip(args, dec_args): | |
assert isinstance(a, t), "arg %r does not match %s" % (a,t) | |
@accepts(int, int) | |
def bar(x,y): | |
return x+y | |
bar(1,1) # return 2 | |
bar(1.0, 1) # throws AssertError |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment