attempt to make value hashable or raise a typeerror if it fails the returned value should generate the same hash for equal values try hash to avoid converting a hashable iterable e g string frozenset to a tuple nonhashable noniterable attempt to make value hashable or raise a typeerror if it fails the returned value should generate the same hash for equal values try hash to avoid converting a hashable iterable e g string frozenset to a tuple non hashable non iterable
from collections.abc import Iterable


def make_hashable(value):
    
    if isinstance(value, dict):
        return tuple(
            [
                (key, make_hashable(nested_value))
                for key, nested_value in sorted(value.items())
            ]
        )
    
    
    try:
        hash(value)
    except TypeError:
        if isinstance(value, Iterable):
            return tuple(map(make_hashable, value))
        
        raise
    return value