import six
from typing import OrderedDict


def map_dict_keys(func, dict_):
    """ applies a function to each of the keys in a dictionary

    Args:
        func (callable): a function
        dict_ (dict): a dictionary

    Returns:
        newdict: transformed dictionary

    CommandLine:
        python -m utool.util_dict --test-map_dict_keys

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_dict import *  # NOQA
        >>> import utool as ut
        >>> dict_ = {'a': [1, 2, 3], 'b': []}
        >>> func = ord
        >>> newdict = map_dict_keys(func, dict_)
        >>> result = ut.repr2(newdict)
        >>> ut.assert_raises(AssertionError, map_dict_keys, len, dict_)
        >>> print(result)
        {97: [1, 2, 3], 98: []}
    """
    if not hasattr(func, '__call__'):
        func = func.__getitem__
        # op.itemgetter(func)
    keyval_list = [(func(key), val) for key, val in six.iteritems(dict_)]
    # newdict = type(dict_)(keyval_list)
    dictclass = OrderedDict if isinstance(dict_, OrderedDict) else dict
    newdict = dictclass(keyval_list)
    assert len(newdict) == len(dict_), (
        'multiple input keys were mapped to the same output key')
    return newdict