'Generate a graphviz dot graph from the classes that
were passed in to __init__.
*name* is the name of the graph.
*urls* is a dictionary mapping class names to HTTP URLs.
*graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
key/value pairs to pass on as graphviz properties.'

def generate_dot(self, name, parts=0, urls={}, env=None, graph_attrs={}, node_attrs={}, edge_attrs={}):

    g_attrs = self.default_graph_attrs.copy()
    n_attrs = self.default_node_attrs.copy()
    e_attrs = self.default_edge_attrs.copy()
    g_attrs.update(graph_attrs)
    n_attrs.update(node_attrs)
    e_attrs.update(edge_attrs)
    if env:
        g_attrs.update(env.config.inheritance_graph_attrs)
        n_attrs.update(env.config.inheritance_node_attrs)
        e_attrs.update(env.config.inheritance_edge_attrs)
    res = []
    res.append(('digraph    %s    {\n' % name))
    res.append(self._format_graph_attrs(g_attrs))
    for cls in self.all_classes:
        if ((not self.show_builtins) and (cls in __builtins__.values())):
            continue
        name = self.class_name(cls, parts)
        this_node_attrs = n_attrs.copy()
        url = urls.get(self.class_name(cls))
        if (url is not None):
            this_node_attrs['URL'] = ('"%s"' % url)
        res.append(('        "%s"    [%s];\n' % (name, self._format_node_attrs(this_node_attrs))))
        for base in cls.__bases__:
            if ((not self.show_builtins) and (base in __builtins__.values())):
                continue
            base_name = self.class_name(base, parts)
            res.append(('        "%s"    ->    "%s"    [%s];\n' % (base_name, name, self._format_node_attrs(e_attrs))))
    res.append('}\n')
    return ''.join(res)
