|
'''
>>> NONE, MEDIUM, STRONG = 0, 1, 2
>>>
>>> @ Accepts (int, int, int)
... Def average (x, y, z ):
... Return (x + y + z)/2
...
>>> Average (5.5, 10, 15.0)
TypeWarning: 'average' method accepts (int, int, int), but was given
(Float, int, float)
15.25
'''
Def accepts (* types, ** kw ):
"Function decorator. Checks that inputs given to decorated function
Are of the expected type.
Parameters:
Types -- The expected types of the inputs to the decorated function.
Must specify type for each parameter.
Kw -- Optional specification of 'debug' level (this is the only valid
Keyword argument, no other shoshould be given ).
Debug = (0 | 1 | 2)
"""
If not kw:
# Default level: MEDIUM
Debug = 1
Else:
Debug = kw ['debug']
Try:
Def decorator (f ):
Def newf (* args ):
If debug = 0:
Return f (* args)
Assert len (args) = len (types)
Argtypes = tuple (map (type, args ))
If argtypes! = Types:
Msg = info (f. _ name __, types, argtypes, 0)
If debug = 1:
Print> sys. stderr, 'typewarning: ', msg
Elif debug = 2:
Raise TypeError, msg
Return f (* args)
Newf. _ name _ = f. _ name __
Return newf
Return decorator
Failed t KeyError, key:
Raise KeyError, key + "is not a valid keyword argument"
Failed t TypeError, msg:
Raise TypeError, msg
Def info (fname, expected, actual, flag ):
"" Convenience function returns nicely formatted error/warning msg ."""
Format = lambda types: ','. join ([str (t). split ("'") [1] for t in types])
Expected, actual = format (expected), format (actual)
Msg = "'% s' method" % fname \
+ ("Accepts", "returns") [flag] + "(% s), but" % expected \
+ ("Was given", "result is") [flag] + "(% s)" % actual
Return msg
|