def method_accepts(exception,**types):
    def check_accepts(f):
        assert ( len(types) + 1 ) == f.func_code.co_argcount, \
        "method_accept number of arguments not equal with "
        "function number of arguments in '%s'" % f.func_name
        @wraps(f)
        def new_f(*args, **kwds):
            argument_types = ", ".join( "%s=%s" %(v,t) for v,t in types.items() )
            for i,v in enumerate(args): # no need to check self argument
                if i == 0 : continue
                if types.has_key(f.func_code.co_varnames[i]) and \
                    not isinstance(v, types[f.func_code.co_varnames[i]]):
                    raise exception("Method argument '%s' with a "
                                    "value of %r does not match the "
                                    "allowed types %s. \n           The "
                                    "arguments of this method have "
                                    "allowed types of %s" % \
                        (f.func_code.co_varnames[i],v,types[f.func_code.co_varnames[i]],argument_types))
                    del types[f.func_code.co_varnames[i]]

            for k,v in kwds.iteritems():
                if types.has_key(k) and not isinstance(v, types[k]):
                    raise exception("Method argument '%s' with a "
                                    "value of %r does not match one "
                                    "of the allowed types %s. \n           The "
                                    "arguments of this method have allowed types of %s" % \
                        (k,v,types[k],argument_types))

            return f(*args, **kwds)
        new_f.func_name = f.func_name
        return new_f
    return check_accepts
Decorator that lets you define what the types
dataset/ETHPy150Open OpenMDAO/OpenMDAO-Framework/openmdao.util/src/openmdao/util/decorators.py/method_accepts