def METHOD_NAME(hasher, obj):
    """
    Update a `hashlib` hasher with a nested object.
    To properly cache nested structures, we need to compute a hash from the
    entire structure, canonicalizing at every level.
    `hasher`'s `.update()` method is called a number of times, touching all of
    `obj` in the process.  Only primitive JSON-safe types are supported.
    """
    hasher.update(str(type(obj)).encode())
    if isinstance(obj, (tuple, list)):
        for e in obj:
            METHOD_NAME(hasher, e)
    elif isinstance(obj, dict):
        for k in sorted(obj):
            METHOD_NAME(hasher, k)
            METHOD_NAME(hasher, obj[k])
    else:
        hasher.update(repr(obj).encode())