Return a string to be used for Graphviz nodes.  The string
    should be short but as informative as possible.

def object_annotation(obj):
    """
    Return a string to be used for Graphviz nodes.  The string
    should be short but as informative as possible.

    """
    # For basic types, use the repr.
    if isinstance(obj, BASE_TYPES):
        return repr(obj)
    if type(obj).__name__ == 'function':
        return "function\\n{}".format(obj.__name__)
    elif isinstance(obj, types.MethodType):
        if six.PY2:
            im_class = obj.im_class
            if im_class is None:
                im_class_name = "<None>"
            else:
                im_class_name = im_class.__name__

            try:
                func_name = obj.__func__.__name__
            except AttributeError:
                func_name = "<anonymous>"
            return "instancemethod\\n{}.{}".format(
                im_class_name,
                func_name,
            )
        else:
            try:
                func_name = obj.__func__.__qualname__
            except AttributeError:
                func_name = "<anonymous>"
            return "instancemethod\\n{}".format(func_name)
    elif isinstance(obj, list):
        return "list[{}]".format(len(obj))
    elif isinstance(obj, tuple):
        return "tuple[{}]".format(len(obj))
    elif isinstance(obj, dict):
        return "dict[{}]".format(len(obj))
    elif isinstance(obj, types.ModuleType):
        return "module\\n{}".format(obj.__name__)
    elif isinstance(obj, type):
        return "type\\n{}".format(obj.__name__)
    elif six.PY2 and isinstance(obj, types.InstanceType):
        return "instance\\n{}".format(obj.__class__.__name__)
    elif isinstance(obj, weakref.ref):
        referent = obj()
        if referent is None:
            return "weakref (dead referent)"
        else:
            return "weakref to id 0x{:x}".format(id(referent))
    elif isinstance(obj, types.FrameType):
        filename = obj.f_code.co_filename
        if len(filename) > FRAME_FILENAME_LIMIT:
            filename = "..." + filename[-(FRAME_FILENAME_LIMIT-3):]
        return "frame\\n{}:{}".format(
            filename,
            obj.f_lineno,
        )
    else:
        return "object\\n{}.{}".format(
            type(obj).__module__,
            type(obj).__name__,
        )