import itertools


def args_combinations(*args, **kwargs):
    """
    Given a bunch of arguments that are all a set of types, generate all
    possible possible combinations of argument type
    args is list of type or set of types
    kwargs is a dict whose values are types or set of types
    """
    def asset(v):
        if isinstance(v, set):
            return v
        else:
            return {v}
    keys = list(kwargs.keys())
    for curr_args in itertools.product(*[asset(a) for a in args]):
        for curr_kwargs in itertools.product(*[asset(kwargs[k]) for k in keys]):
            yield curr_args, {k: v for (k, v) in zip(keys, curr_kwargs)}