/usr/share/pyshared/pycallgraph/output/output.py is in python-pycallgraph 1.0.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import re
import os
from distutils.spawn import find_executable
from ..exceptions import PyCallGraphException
from ..color import Color
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 kwargs.iteritems()]
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 config.__dict__.iteritems():
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 '{}'.format(edge.calls.value)
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
def start(self):
'''Initialise variables after initial configuration.'''
pass
def update(self):
'''Called periodically during a trace, but only when should_update is
set to True.
'''
raise NotImplementedError('update')
def should_update(self):
'''Return True if the update method should be called periodically.'''
return False
def done(self):
'''Called when the trace is complete and ready to be saved.'''
raise NotImplementedError('done')
def ensure_binary(self, cmd):
if find_executable(cmd):
return
raise PyCallGraphException(
'The command "{}" is required to be in your path.'.format(cmd))
def normalize_path(self, path):
regex_user_expand = re.compile('\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,
)
|