Skip to main content
1 of 2

I realise this question is very old, but in python, as far as I know only strings are not session consistent hashes. So you can do something like this. Note that because string hashes are randomised, it means frozen sets cannot be relied upon to give consistent hashest, the below will dismantle the common types collection but depends on a frozen set's elements having a natural ordering, else there is no way to construct a repeatable hash (the set order depends on the hash IIRC, so a frozenset of strings will have different orders in different sessions).

def session_consistent_hash(
        obj : t.Any, hash_object=None
):
    """
    This should be able to take any of the parameters that go into making a metadata object,
    it will essentially function as the hash function for metadata objects which must be
    consistent across python sessions. Python randomises its string hashes.
    """
    if hash_object is None:
        hash_object = hashlib.md5()
    if isinstance(obj, str):
        hash_object.update(obj.encode("utf16"))
    elif isinstance(obj, t.Mapping):
        for key, value in obj.items():
            session_consistent_hash(key, hash_object=hash_object)
            session_consistent_hash(value, hash_object=hash_object)
    elif isinstance(obj, t.Sequence):
        for value in obj:
            session_consistent_hash(value, hash_object=hash_object)
    elif isinstance(obj, t.FrozenSet):
        session_consistent_hash(
            list(sorted(obj)),
            hash_object=hash_object
        )
    else :
        hash_object.update(hash(obj))
    return int(hash_object.hexdigest(), 16)