def __init__(self, **kwargs):
        self.output_file = 'pycallgraph.dot'
        self.font_name = 'Verdana'
        self.font_size = 7
        self.group_font_size = 10
        self.group_border_color = Color(0, 0, 0, 0.8)

        Output.__init__(self, **kwargs)

        self.prepare_graph_attributes()
 def edge_color(self, edge):
     value = float(edge.time.fraction)
     return Color.hsv(value / 2 + .5, value, 0.7)
 def node_color(self, node):
     value = float(node.time.fraction)
     return Color.hsv(value / 2 + .5, value, 0.9)
class DotGraphvizOutput(Output):
    """
    Generates
    """
    def __init__(self, **kwargs):
        self.output_file = 'pycallgraph.dot'
        self.font_name = 'Verdana'
        self.font_size = 7
        self.group_font_size = 10
        self.group_border_color = Color(0, 0, 0, 0.8)

        Output.__init__(self, **kwargs)

        self.prepare_graph_attributes()

    def prepare_graph_attributes(self):
        generated_message = '\\n'.join([
            r'Generated by Python Call Graph v%s' % __version__,
            r'http://pycallgraph.slowchop.com',
        ])

        self.graph_attributes = {
            'graph': {
                'overlap': 'scalexy',
                'fontname': self.font_name,
                'fontsize': self.font_size,
                'fontcolor': Color(0, 0, 0, 0.5).rgba_web(),
                'label': generated_message,
            },
            'node': {
                'fontname': self.font_name,
                'fontsize': self.font_size,
                'fontcolor': Color(0, 0, 0).rgba_web(),
                'style': 'filled',
                'shape': 'rect',
            },
            'edge': {
                'fontname': self.font_name,
                'fontsize': self.font_size,
                'fontcolor': Color(0, 0, 0).rgba_web(),
            }
        }

    def done(self):
        source = self.generate()

        self.debug(source)

        with open(self.output_file, 'w') as f:
            f.write(source)

    def generate(self):
        '''Returns a string with the contents of a DOT file for Graphviz to
        parse.
        '''
        indent_join = '\n' + ' ' * 12

        return textwrap.dedent('''\
        digraph G {{

            // Attributes
            {}

            // Groups
            {}

            // Nodes
            {}

            // Edges
            {}

        }}
        '''.format(
            indent_join.join(self.generate_attributes()),
            indent_join.join(self.generate_groups()),
            indent_join.join(self.generate_nodes()),
            indent_join.join(self.generate_edges()),
        ))

    def attrs_from_dict(self, d):
        output = []
        for attr, val in d.iteritems():
            output.append('%s = "%s"' % (attr, val))
        return ', '.join(output)

    def node(self, key, attr):
        return '"{}" [{}];'.format(
            key, self.attrs_from_dict(attr),
        )

    def edge(self, edge, attr):
        return '"{0.src_func}" -> "{0.dst_func}" [{1}];'.format(
            edge, self.attrs_from_dict(attr),
        )

    def generate_attributes(self):
        output = []
        for section, attrs in self.graph_attributes.iteritems():
            output.append('{} [ {} ];'.format(
                section, self.attrs_from_dict(attrs),
            ))
        return output

    def generate_groups(self):
        if not self.processor.config.groups:
            return ''

        output = []
        for group, nodes in self.processor.groups():
            funcs = [node.name for node in nodes]
            funcs = '" "'.join(funcs)
            group_color = self.group_border_color.rgba_web()
            group_font_size = self.group_font_size
            output.append(
                'subgraph "cluster_{group}" {{ '
                '"{funcs}"; '
                'label = "{group}"; '
                'fontsize = "{group_font_size}"; '
                'fontcolor = "black"; '
                'style = "bold"; '
                'color="{group_color}"; }}'.format(**locals()))
        return output

    def generate_nodes(self):
        output = []
        for node in self.processor.nodes():
            attr = {
                'color': self.node_color_func(node).rgba_web(),
                'label': self.node_label_func(node),
            }
            output.append(self.node(node.name, attr))

        return output

    def generate_edges(self):
        output = []

        for edge in self.processor.edges():
            attr = {
                'color': self.edge_color_func(edge).rgba_web(),
                'label': self.edge_label_func(edge),
            }
            output.append(self.edge(edge, attr))

        return output
 def edge_color(self, edge):
     value = float(edge.time.fraction)
     return Color.hsv(value / 2 + .5, value, 0.7)
 def node_color(self, node):
     value = float(node.time.fraction)
     return Color.hsv(value / 2 + .5, value, 0.9)