Skip to content

Instantly share code, notes, and snippets.

@tav
Created July 24, 2009 20:57
Show Gist options
  • Select an option

  • Save tav/154549 to your computer and use it in GitHub Desktop.

Select an option

Save tav/154549 to your computer and use it in GitHub Desktop.
# Copyright (c) 2009 Metanational Commons Ltd.
from time import time
from sha import new as sha1
CO_VARARGS = 4
CO_VARKEYWORDS = 8
def validate(**spec):
def __decorate(func):
rkey = sha1(str(time())).hexdigest()[:8]
rkw = 'kw_%s' % rkey
code = func.func_code
varnames = list(code.co_varnames)
defaults = func.func_defaults or ()
varargs = varkwargs = None
if code.co_flags & CO_VARKEYWORDS:
varkwargs = varnames.pop(-1)
if code.co_flags & CO_VARARGS:
varargs = varnames.pop(-1)
params = [varnames.pop(0)]; add = params.append
params2 = params[:]; add2 = params2.append
default_pointer = len(varnames) - len(defaults)
for idx, varname in enumerate(varnames):
if idx < default_pointer:
add(varname)
add2("%s[%r]" % (rkw, varname))
else:
add("%s=defaults_%s[%s]" % (varname, rkey, idx-default_pointer))
add2("%s=%s.get(%r, defaults_%s[%s])" % (varname, rkw, varname, rkey, idx-default_pointer))
if varargs:
add("*%s" % varargs)
add2("*%s[%r]" % (rkw, varargs))
if varkwargs:
add("**%s" % varkwargs)
add2("**%s[%r]" % (rkw, varkwargs))
params = ", ".join(params)
params2 = ", ".join(params2)
source = """
def newfunc(%(params)s):
kwargs_%(r)s = locals()
kw_%(r)s = {}
for key_%(r)s in kwargs_%(r)s:
if key_%(r)s in spec_%(r)s:
kw_%(r)s[key_%(r)s] = spec_%(r)s[key_%(r)s](kwargs_%(r)s[key_%(r)s])
else:
kw_%(r)s[key_%(r)s] = kwargs_%(r)s[key_%(r)s]
return func_%(r)s(%(params2)s)
""" % dict(params=params, params2=params2, r=rkey)
print source
env = {
'func_%s' % rkey: func,
'spec_%s' % rkey: spec,
'defaults_%s' % rkey: defaults,
}
exec source in env
return env['newfunc']
return __decorate
@validate(a=float, b=str, c=int)
def foo(ctx, a, b, c=3, d=4, **kwargs):
print "a:", `a`
print "b:", `b`
print "c:", `c`
print "d:", `d`
print "kwargs:", `kwargs`
def foo2(ctx, a, b, c=3, d=4, **kwargs):
print "a:", `a`
print "b:", `b`
print "c:", `c`
print "d:", `d`
print "kwargs:", `kwargs`
@validate(a=float, b=str)
def bar(ctx, a, b, *args, **kwargs):
print
print "a:", `a`
print "b:", `b`
print "args:", `args`
print "kwargs:", `kwargs`
print
@validate(a=float, b=str)
def spam(ctx, a, b, *args):
print
print "a:", `a`
print "b:", `b`
print "args:", `args`
print
@validate(a=int, b=str)
def blah(ctx, a, b):
print
print "a:", `a`
print "b:", `b`
print
@validate(a=float, b=str, c=int)
def yam(ctx, a, b, c=3, d=4, **kwargs):
pass
def validate2(**spec):
def __decorate(func):
def __decorated(*args, **kwargs):
return func(*args, **kwargs)
return __decorated
return __decorate
@validate2(a=float, b=str, c=int)
def yam2(ctx, a, b, c=3, d=4, **kwargs):
pass
def yam3(ctx, a, b, c=3, d=4, **kwargs):
pass
foo(None, 20, 'hello', 4, 33, random='foo')
bar(None, 20, 'hello', 4, 33, random='foo')
spam(None, 20, 'hello', 4, 33, 'foo')
blah(None, 20, 'hello')
start = time()
for i in xrange(10000):
yam(None, 20, 'hello', 4, 33, random='foo')
end = time()
start2 = time()
for i in xrange(10000):
yam2(None, 20, 'hello', 4, 33, random='foo')
end2 = time()
start3 = time()
for i in xrange(10000):
yam3(None, 20, 'hello', 4, 33, random='foo')
end3 = time()
print "Native:", end3 - start3
print "Decorated:", end2 - start2
print "Validated:", end - start
print "Multiplier:", (end - start) / (end2 - start2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment