+
+
Source code for pycallgraph.output.output
+import re
+import os
+from shutil import which
+
+from ..exceptions import PyCallGraphException
+from ..color import Color
+
+
+
+
[docs]
+
class Output(object):
+
'''Base class for all outputters.'''
+
+
def __init__(self, **kwargs):
+
self.node_color_func = self.node_color
+
self.edge_color_func = self.edge_color
+
self.node_label_func = self.node_label
+
self.edge_label_func = self.edge_label
+
+
# Update the defaults with anything from kwargs
+
[setattr(self, k, v) for k, v in list(kwargs.items())]
+
+
+
[docs]
+
def set_config(self, config):
+
'''
+
This is a quick hack to move the config variables set in Config into
+
the output module config variables.
+
'''
+
for k, v in list(config.__dict__.items()):
+
if hasattr(self, k) and \
+
callable(getattr(self, k)):
+
continue
+
setattr(self, k, v)
+
+
+
def node_color(self, node):
+
value = float(node.time.fraction * 2 + node.calls.fraction) / 3
+
return Color.hsv(value / 2 + .5, value, 0.9)
+
+
def edge_color(self, edge):
+
value = float(edge.time.fraction * 2 + edge.calls.fraction) / 3
+
return Color.hsv(value / 2 + .5, value, 0.7)
+
+
def node_label(self, node):
+
parts = [
+
'{0.name}',
+
'calls: {0.calls.value:n}',
+
'time: {0.time.value:f}s',
+
]
+
+
if self.processor.config.memory:
+
parts += [
+
'memory in: {0.memory_in.value_human_bibyte}',
+
'memory out: {0.memory_out.value_human_bibyte}',
+
]
+
+
return r'\n'.join(parts).format(node)
+
+
def edge_label(self, edge):
+
return '{0}'.format(edge.calls.value)
+
+
+
[docs]
+
def sanity_check(self):
+
'''Basic checks for certain libraries or external applications. Raise
+
or warn if there is a problem.
+
'''
+
pass
+
+
+
@classmethod
+
def add_arguments(cls, subparsers):
+
pass
+
+
def reset(self):
+
pass
+
+
def set_processor(self, processor):
+
self.processor = processor
+
+
+
[docs]
+
def start(self):
+
'''Initialise variables after initial configuration.'''
+
pass
+
+
+
+
[docs]
+
def update(self):
+
'''Called periodically during a trace, but only when should_update is
+
set to True.
+
'''
+
raise NotImplementedError('update')
+
+
+
+
[docs]
+
def should_update(self):
+
'''Return True if the update method should be called periodically.'''
+
return False
+
+
+
+
[docs]
+
def done(self):
+
'''Called when the trace is complete and ready to be saved.'''
+
raise NotImplementedError('done')
+
+
+
def ensure_binary(self, cmd):
+
if which(cmd):
+
return
+
+
raise PyCallGraphException(
+
'The command "{0}" is required to be in your path.'.format(cmd))
+
+
def normalize_path(self, path):
+
regex_user_expand = re.compile(r'\A~')
+
if regex_user_expand.match(path):
+
path = os.path.expanduser(path)
+
else:
+
path = os.path.expandvars(path) # expand, just in case
+
return path
+
+
def prepare_output_file(self):
+
if self.fp is None:
+
self.output_file = self.normalize_path(self.output_file)
+
self.fp = open(self.output_file, 'wb')
+
+
def verbose(self, text):
+
self.processor.config.log_verbose(text)
+
+
def debug(self, text):
+
self.processor.config.log_debug(text)
+
+
@classmethod
+
def add_output_file(cls, subparser, defaults, help):
+
subparser.add_argument(
+
'-o', '--output-file', type=str, default=defaults.output_file,
+
help=help,
+
)
+
+
+
+
+