Skip to content

Instantly share code, notes, and snippets.

@io41
Created January 4, 2012 18:36
Show Gist options
  • Save io41/1561390 to your computer and use it in GitHub Desktop.
Save io41/1561390 to your computer and use it in GitHub Desktop.
import functools
import inspect
# OMG, what have I done!? (Don't read this bit. Ever.)
class inject(object):
@classmethod
def require(__cls, *args):
def decorator(func):
functools.wraps(func)
def wrapper(**kwargs):
required_args = [arg for arg in args if arg not in kwargs]
if required_args:
raise Exception("Missing required args {} for function {}".format(
', '.join(required_args),
func.__name__)
)
members = inspect.getmembers(func)
__func_code = [v for k, v in members if k == '__code__'][0]
__func_globals = [v for k, v in members if k == 'func_globals'][0]
def real(**kw):
exec ';'.join('{}={}'.format(arg, kw[arg]) for arg in args) in locals(), __func_globals
__func_globals.update(locals())
return eval(__func_code, __func_globals)
return real(**kwargs)
if wrapper.__doc__:
wrapper.__doc__ = 'Requires {}\n{}'.format(', '.join(args), wrapper.__doc__)
else:
wrapper.__doc__ = 'Requires {}'.format(', '.join(args))
return wrapper
return decorator
# Usage
@inject.require('r1', 'r2')
def foo1():
print 'r1:', r1
print 'r2:', r2
print "and also in kw", kw
foo2(**kw)
return "har har" # return values work too
@inject.require('r3', 'r1')
def foo2():
print "Look ma, r3 as a var:", r3
print "AND in kw['r3']:",kw['r3']
retval = foo1(r1=1, r2=2, r3=3, r4=4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment