'Generate a graphviz dot graph from the classes that
were passed in to __init__.
*fd* is a Python file-like object to write to.
*name* is the name of the graph
*urls* is a dictionary mapping class names to http urls
*graph_options*, *node_options*, *edge_options* are
dictionaries containing key/value pairs to pass on as graphviz
properties.'

def generate_dot(self, fd, name, parts=0, urls={}, graph_options={}, node_options={}, edge_options={}):

    g_options = self.default_graph_options.copy()
    g_options.update(graph_options)
    n_options = self.default_node_options.copy()
    n_options.update(node_options)
    e_options = self.default_edge_options.copy()
    e_options.update(edge_options)
    fd.write(('digraph    %s    {\n' % name))
    fd.write(self._format_graph_options(g_options))
    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_options = n_options.copy()
        url = urls.get(self.class_name(cls))
        if (url is not None):
            this_node_options['URL'] = ('"%s"' % url)
        fd.write(('        "%s"    [%s];\n' % (name, self._format_node_options(this_node_options))))
        for base in cls.__bases__:
            if ((not self.show_builtins) and (base in __builtins__.values())):
                continue
            base_name = self.class_name(base, parts)
            fd.write(('        "%s"    ->    "%s"    [%s];\n' % (base_name, name, self._format_node_options(e_options))))
    fd.write('}\n')
