def recur_freeze_containers(mutable_obj, ignoredtypes=_PYTHON_PRIMITIVE_TYPES):
    """
    dict -> namedtuple (!WARNING! keys can only be [a-zA-Z][a-zA-Z0-9_]*)
    list -> tuple
    set -> frozenset
   """
    if is_mapping(mutable_obj):
        copy = dict(mutable_obj)
        items = copy.iteritems()
    elif is_sequence(mutable_obj):
        copy = list(mutable_obj)
        items = zip(xrange(0, len(copy)), copy)
    elif is_set(mutable_obj):
        return frozenset(mutable_obj)
    elif isinstance(mutable_obj, ignoredtypes):
        return mutable_obj
    else:
        raise TypeError("Cannot freeze {!r} of unsupported data type {}".format(mutable_obj, type(mutable_obj)))

    for k,v in items:
        copy[k] = recur_freeze_containers(v, ignoredtypes)

    if is_mapping(copy):
        return _dict2NamedTuple(copy)
    elif is_sequence(copy):
        return tuple(copy)
def recur_unfreeze_containers(frozen_obj, ignoredtypes=_PYTHON_PRIMITIVE_TYPES):
    """
    namedtuple -> dict
    tuple -> list
    frozenset -> set
    """
    if hasattr(frozen_obj, '_asdict'):
        new = frozen_obj._asdict()
        items = new.iteritems()
    elif is_sequence(frozen_obj):
        new = list(frozen_obj)
        items = zip(xrange(0, len(new)), new)
    elif is_set(frozen_obj):
        return set(frozen_obj)
    elif isinstance(frozen_obj, ignoredtypes):
        return frozen_obj
    else:
        raise TypeError("Cannot unfreeze {!r} of unsupported data type {}".format(frozen_obj, type(frozen_obj)))

    for k,v in items:
        new[k] = recur_unfreeze_containers(v, ignoredtypes)

    return new