from typing import MutableMapping


def flatten_dict(d, reducer=None, parent_key=()):
    """Flattens dict into single-level-tuple-keyed dict with
        {(tuple of keys of parents and self): value}

    Args:
        reducer:
            Character to join keys in a tuple.
            If None, returns with key as a tuple.
    Returns:
        dict of {
            (key_lvl1, key_lvl2, key_lvl3, ...): value
        }
    """
    items = []
    for k, v in d.items():
        new_key = parent_key + (k if isinstance(k, tuple) else (k,))
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, parent_key=new_key).items())
        else:
            items.append((new_key, v))
    if reducer:
        return {reducer.join(k): v for k, v in type(d)(items).items()}
    else:
        return type(d)(items)