Source code for libutilitaspy.general.decorators

"""
This module contains some generally useful function and method decorators.
"""

[docs]def sig(params, ret): """ Decorator for functions: decorates a function with parameter and return types. Type checking is performed dynamically. Typical use:: @sig([type_1, ..., type_n], type_ret) def func(param_1, ..., param_n): ... return ... When invoking `func(arg_1, ..., arg_n)`, this decorator checks that `arg_i` is an instance of `type_i`, and that the returned value is an instance of `type_ret`. :param params: list of parameter's types :type params: type list :param type ret: return type :returns: A "typecheck" function which accepts as parameter a function f and returns the decorated function. :rtype: function decorator (function -> function) """ def typecheck(f): def new_f(*args): assert len(args) == len(params), "Wrong number of arguments in function %s: it has %d parameters, but %d arguments were passed." % (f.__name__, len(params), len(args)) i = 1 for arg, param in zip(args, params): postfix = 'th' if i > 2 else 'nd' if i == 2 else 'st' assert isinstance(arg, param), "Bad argument type in function %s: the %d-%s argument is of type %s, but the corresponding parameter must be of type %s." % (f.__name__, i, postfix, type(arg).__name__, param.__name__) i += 1 result = f(*args) assert isinstance(result, ret), "Bad return type in function %s: it returned a value of type %s but it should return a value of type %s" % (f.__name__, type(result).__name__, ret.__name__) return result return new_f return typecheck
[docs]def msig(params, ret): """ Decorator for methods: decorates a method with parameter and return types. Type checking is performed dynamically. This is just like the sig decorator, but ignores the first argument. Typical use:: @msig([type_1, ..., type_n], type_ret) def meth(self, param_1, ..., param_n): ... return ... When invoking `func(arg_1, ..., arg_n)`, this decorator checks that `arg_i` is an instance of `type_i`, and that the returned value is an instance of `type_ret`. :param params: list of parameter's types :type params: type list :param type ret: return type :returns: A "typecheck" function which accepts as parameter a function f and returns the decorated function. :rtype: method decorator (method -> method) """ def typecheck(f): def new_f(*args): assert len(args) > 0, "Instance method %s called without an instance." % f.__name__ self = args[0] assert len(args) - 1 == len(params), "Wrong number of arguments in method %s of class %s: it has %d parameters (excluding 'self'), but %d arguments were passed." % (f.__name__, self.__class__.__name__, len(params), len(args) - 1) i = 1 for arg, param in zip(args[1:], params): postfix = 'th' if i > 2 else 'nd' if i == 2 else 'st' assert isinstance(arg, param), "Bad argument type in method %s of class %s: the %d-%s argument is of type %s, but the corresponding parameter must be of type %s." % (f.__name__, self.__class__.__name__, i, postfix, type(arg).__name__, param.__name__) i += 1 result = f(*args) assert isinstance(result, ret), "Bad return type in method %s of class %s: it returned a value of type %s but it should return a value of type %s" % (f.__name__, self.__class__.__name__, type(result).__name__, ret.__name__) return result return new_f return typecheck