
def checkArguments(patterns):
    def decorate(func):
        def check_and_call(*args, **kwargs):
            if len(patterns) == 0:
                return func(*args, **kwargs)
            
            # Create hash with argument name as key and specified value as value.
            # If no value was specified for a (keyword) argument, its default
            # value is used.
            arguments = {}
            
            # Get argument names of function:
            co_varnames = func.__code__.co_varnames
            
            # Add positioned arguments:
            for i, val in enumerate(args):
                arg_name = co_varnames[i]
                arguments[arg_name] = val
                
            # Add keyword arguments:
            for key in kwargs:
                arguments[key] = kwargs[key]
                
            # Get number of arguments (withount *args and **kwargs):
            co_argcount = func.__code__.co_argcount
            
            default_values = func.__defaults__
            
            # Add default values:
            if default_values is not None:
                for i, key in enumerate(co_varnames[co_argcount-len(default_values):co_argcount]):
                    if key not in arguments:
                        arguments[key] = default_values[i]

            for p, pattern in enumerate(patterns):
                for entry in pattern:
                    if isinstance(entry, str):
                        if entry not in arguments:
                            break
                    if isinstance(entry, dict):
                        for key in entry:
                            try:
                                if not arguments[key] == entry[key]:
                                    break     #  ::::.
                            except KeyError:  #     ::
                                # Argument not set  ::
                                break         #  :::::
                        else:                 #     ::
                            continue          #     ::
                        break                 # <::::'
                else:
                    # Set non-keyword arguments, that were not set, to None so that
                    # we won't get a Error saying that an argument is missing.
                    len_default_values = 0
                    if default_values is not None:
                        len_default_values = len(default_values)
                    for arg in co_varnames[:co_argcount-len_default_values]:
                        if arg not in arguments:
                            arguments[arg] = None
                    
                    # Send index of the selected pattern to the function:
                    if arguments.has_key('_argument_pattern'):
                        arguments['_argument_pattern'] = p
                    return func(**arguments)
            else:
                raise ValueError('No argument pattern matched the given arguments.')
        return check_and_call
    return decorate


