[Python-3000] Fwd: Conventions for annotation consumers
Ron Adam
rrr at ronadam.com
Sun Aug 20 23:01:46 CEST 2006
Paul Prescod wrote:
> I guess I still don't really understand what he's getting at or what the
> value of @callmeta is in that example. It just seems like extra noise
> with no value to me...
>
> Ron: what *precisely* does the @callmeta decorator do? If you can
> express it in code, so much the better.
>
> Paul Prescod
>
Here's a working example. @callmeta could be named something else like
@asserter, @checker, or whatever. And it should do more checks to avoid
non callable annotations and to keep from writing over pre existing
annotations, etc...
As I said this could all be put in a module and it's easy to create new
assert tests without having to know about decorators or any special classes.
Ron
# ----- Some assert test functions.
def IsAny(arg): pass
def IsNumber(arg):
assert type(arg) in (int, long, float), \
"%r is not a number" % arg
def IsInt(arg):
assert type(arg) in (int, long), \
"%r is not an Int" % arg
def IsFloat(arg):
assert isinstance(arg, float), \
"%r is not a flaot" % arg
def InRange(start, stop):
def inrange(arg):
assert start <= arg <= stop, \
"%r is not in range %r through %r" % (arg, start, stop)
return inrange
def InSet(list_):
s = set(list_)
def inset(arg):
assert arg in s, \
"%r is not in %r" % (arg, s)
return inset
# ------- The add-annotation decorator.
def annotate(**kwds):
def setter(func):
func.__setattr__('__signature__', dict())
func.__signature__['annotations'] = kwds
return func
return setter
# ------ The do-asserts decorator.
def callmeta(f):
def new_f(*args, **kwds):
d = dict(zip(f.func_code.co_varnames, args))
d.update(kwds)
tests = f.__signature__['annotations']
for key in d:
if key != 'returns':
tests[key](d[key])
result = f(*args, **kwds)
if 'returns' in tests:
tests['returns'](result)
return result
new_f.func_name = f.func_name
return new_f
# --------- Examples of using callable annotations.
@callmeta
@annotate(a=Any, b=IsInt, returns=IsInt)
def add(a, b):
return a + b
print add(1, 4)
@callmeta
@annotate(a=IsInt, b=IsInt, returns=IsInt)
def add(a, b):
return a + b
print add(1, 4.1) # assertion error here.
# which could also be...
"""
@callmeta
def add(a:IsInt, b:IsInt) ->IsInt:
return a + b
"""
More information about the Python-3000
mailing list