''' >>> 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 |