[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.


# ----- 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))
         tests = f.__signature__['annotations']
         for key in d:
             if key != 'returns':
         result = f(*args, **kwds)
         if 'returns' in tests:
         return result
     new_f.func_name = f.func_name
     return new_f

# --------- Examples of using callable annotations.

@annotate(a=Any, b=IsInt, returns=IsInt)
def add(a, b):
     return a + b

print add(1, 4)

@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...

def add(a:IsInt, b:IsInt) ->IsInt:
     return a + b

More information about the Python-3000 mailing list