* [gentoo-commits] gentoo-x86 commit in dev-util/gprof2dot/files: gprof2dot-0_p20100216-python3.patch
@ 2012-03-15 20:16 Sebastian Pipping (sping)
0 siblings, 0 replies; only message in thread
From: Sebastian Pipping (sping) @ 2012-03-15 20:16 UTC (permalink / raw
To: gentoo-commits
sping 12/03/15 20:16:55
Added: gprof2dot-0_p20100216-python3.patch
Log:
dev-util/gprof2dot: Python 3.x (bug #341687)
(Portage version: 2.1.10.49/cvs/Linux x86_64)
Revision Changes Path
1.1 dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch?rev=1.1&content-type=text/plain
Index: gprof2dot-0_p20100216-python3.patch
===================================================================
From 6087a16e81d5c41647e05291dd25bb6eac9493eb Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Fri, 5 Nov 2010 18:10:29 +0100
Subject: [PATCH] Support both Python 2.x and 3.x
---
gprof2dot.py | 138 ++++++++++++++++++++++++++++++++++------------------------
1 files changed, 81 insertions(+), 57 deletions(-)
diff --git a/gprof2dot.py b/gprof2dot.py
index bf0aba8..888081f 100755
--- a/gprof2dot.py
+++ b/gprof2dot.py
@@ -32,6 +32,27 @@ import optparse
import xml.parsers.expat
+# Python 2.x/3.x compatibility
+if sys.version_info[0] == 3:
+ PYTHON_3 = True
+ def compat_iteritems(x): return x.items() # No iteritems() in Python 3
+ def compat_itervalues(x): return x.values() # No itervalues() in Python 3
+ def compat_keys(x): return list(x.keys()) # keys() is a generator in Python 3
+ compat_basestring = str # No class basestring in Python 3
+
+ CALL_TIMES_FORMAT = "%u\xd7" # All strings are unicode in Python 3, no u"" marking
+else:
+ PYTHON_3 = False
+ def compat_iteritems(x): return x.iteritems()
+ def compat_itervalues(x): return x.itervalues()
+ def compat_keys(x): return x.keys()
+ compat_basestring = basestring
+
+ # u"" strings not supported in Python 3
+ # By using eval() we don't get a syntax error
+ CALL_TIMES_FORMAT = eval('u"%u\xd7"')
+
+
try:
# Debugging helper module
import debug
@@ -40,7 +61,7 @@ except ImportError:
def times(x):
- return u"%u\xd7" % (x,)
+ return CALL_TIMES_FORMAT % (x,)
def percentage(p):
return "%.02f%%" % (p*100.0,)
@@ -236,8 +257,8 @@ class Profile(Object):
def validate(self):
"""Validate the edges."""
- for function in self.functions.itervalues():
- for callee_id in function.calls.keys():
+ for function in compat_itervalues(self.functions):
+ for callee_id in compat_keys(function.calls):
assert function.calls[callee_id].callee_id == callee_id
if callee_id not in self.functions:
sys.stderr.write('warning: call to undefined function %s from function %s\n' % (str(callee_id), function.name))
@@ -248,11 +269,11 @@ class Profile(Object):
# Apply the Tarjan's algorithm successively until all functions are visited
visited = set()
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
if function not in visited:
self._tarjan(function, 0, [], {}, {}, visited)
cycles = []
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
if function.cycle is not None and function.cycle not in cycles:
cycles.append(function.cycle)
self.cycles = cycles
@@ -275,7 +296,7 @@ class Profile(Object):
order += 1
pos = len(stack)
stack.append(function)
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
callee = self.functions[call.callee_id]
# TODO: use a set to optimize lookup
if callee not in orders:
@@ -299,10 +320,10 @@ class Profile(Object):
for cycle in self.cycles:
cycle_totals[cycle] = 0.0
function_totals = {}
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
function_totals[function] = 0.0
- for function in self.functions.itervalues():
- for call in function.calls.itervalues():
+ for function in compat_itervalues(self.functions):
+ for call in compat_itervalues(function.calls):
if call.callee_id != function.id:
callee = self.functions[call.callee_id]
function_totals[callee] += call[event]
@@ -310,8 +331,8 @@ class Profile(Object):
cycle_totals[callee.cycle] += call[event]
# Compute the ratios
- for function in self.functions.itervalues():
- for call in function.calls.itervalues():
+ for function in compat_itervalues(self.functions):
+ for call in compat_itervalues(function.calls):
assert call.ratio is None
if call.callee_id != function.id:
callee = self.functions[call.callee_id]
@@ -332,10 +353,10 @@ class Profile(Object):
# Sanity checking
assert outevent not in self
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
assert outevent not in function
assert inevent in function
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
assert outevent not in call
if call.callee_id != function.id:
assert call.ratio is not None
@@ -343,13 +364,13 @@ class Profile(Object):
# Aggregate the input for each cycle
for cycle in self.cycles:
total = inevent.null()
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
total = inevent.aggregate(total, function[inevent])
self[inevent] = total
# Integrate along the edges
total = inevent.null()
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
total = inevent.aggregate(total, function[inevent])
self._integrate_function(function, outevent, inevent)
self[outevent] = total
@@ -360,7 +381,7 @@ class Profile(Object):
else:
if outevent not in function:
total = function[inevent]
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
if call.callee_id != function.id:
total += self._integrate_call(call, outevent, inevent)
function[outevent] = total
@@ -381,7 +402,7 @@ class Profile(Object):
total = inevent.null()
for member in cycle.functions:
subtotal = member[inevent]
- for call in member.calls.itervalues():
+ for call in compat_itervalues(member.calls):
callee = self.functions[call.callee_id]
if callee.cycle is not cycle:
subtotal += self._integrate_call(call, outevent, inevent)
@@ -390,9 +411,9 @@ class Profile(Object):
# Compute the time propagated to callers of this cycle
callees = {}
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
if function.cycle is not cycle:
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
callee = self.functions[call.callee_id]
if callee.cycle is cycle:
try:
@@ -403,7 +424,7 @@ class Profile(Object):
for member in cycle.functions:
member[outevent] = outevent.null()
- for callee, call_ratio in callees.iteritems():
+ for callee, call_ratio in compat_iteritems(callees):
ranks = {}
call_ratios = {}
partials = {}
@@ -418,7 +439,7 @@ class Profile(Object):
def _rank_cycle_function(self, cycle, function, rank, ranks):
if function not in ranks or ranks[function] > rank:
ranks[function] = rank
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
if call.callee_id != function.id:
callee = self.functions[call.callee_id]
if callee.cycle is cycle:
@@ -427,7 +448,7 @@ class Profile(Object):
def _call_ratios_cycle(self, cycle, function, ranks, call_ratios, visited):
if function not in visited:
visited.add(function)
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
if call.callee_id != function.id:
callee = self.functions[call.callee_id]
if callee.cycle is cycle:
@@ -438,7 +459,7 @@ class Profile(Object):
def _integrate_cycle_function(self, cycle, function, partial_ratio, partials, ranks, call_ratios, outevent, inevent):
if function not in partials:
partial = partial_ratio*function[inevent]
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
if call.callee_id != function.id:
callee = self.functions[call.callee_id]
if callee.cycle is not cycle:
@@ -465,7 +486,7 @@ class Profile(Object):
"""Aggregate an event for the whole profile."""
total = event.null()
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
try:
total = event.aggregate(total, function[event])
except UndefinedEvent:
@@ -475,11 +496,11 @@ class Profile(Object):
def ratio(self, outevent, inevent):
assert outevent not in self
assert inevent in self
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
assert outevent not in function
assert inevent in function
function[outevent] = ratio(function[inevent], self[inevent])
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
assert outevent not in call
if inevent in call:
call[outevent] = ratio(call[inevent], self[inevent])
@@ -489,13 +510,13 @@ class Profile(Object):
"""Prune the profile"""
# compute the prune ratios
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
try:
function.weight = function[TOTAL_TIME_RATIO]
except UndefinedEvent:
pass
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
callee = self.functions[call.callee_id]
if TOTAL_TIME_RATIO in call:
@@ -509,24 +530,24 @@ class Profile(Object):
pass
# prune the nodes
- for function_id in self.functions.keys():
+ for function_id in compat_keys(self.functions):
function = self.functions[function_id]
if function.weight is not None:
if function.weight < node_thres:
del self.functions[function_id]
# prune the egdes
- for function in self.functions.itervalues():
- for callee_id in function.calls.keys():
+ for function in compat_itervalues(self.functions):
+ for callee_id in compat_keys(function.calls):
call = function.calls[callee_id]
if callee_id not in self.functions or call.weight is not None and call.weight < edge_thres:
del function.calls[callee_id]
def dump(self):
- for function in self.functions.itervalues():
+ for function in compat_itervalues(self.functions):
sys.stderr.write('Function %s:\n' % (function.name,))
self._dump_events(function.events)
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
callee = self.functions[call.callee_id]
sys.stderr.write(' Call %s:\n' % (callee.name,))
self._dump_events(call.events)
@@ -537,7 +558,7 @@ class Profile(Object):
sys.stderr.write(' Function %s\n' % (function.name,))
def _dump_events(self, events):
- for event, value in events.iteritems():
+ for event, value in compat_iteritems(events):
sys.stderr.write(' %s: %s\n' % (event.name, event.format(value)))
@@ -695,7 +716,7 @@ class XmlTokenizer:
self.final = len(data) < size
try:
self.parser.Parse(data, self.final)
- except xml.parsers.expat.ExpatError, e:
+ except xml.parsers.expat.ExpatError as e:
#if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS:
if e.code == 3:
pass
@@ -801,7 +822,7 @@ class GprofParser(Parser):
"""Extract a structure from a match object, while translating the types in the process."""
attrs = {}
groupdict = mo.groupdict()
- for name, value in groupdict.iteritems():
+ for name, value in compat_iteritems(groupdict):
if value is None:
value = None
elif self._int_re.match(value):
@@ -977,7 +998,7 @@ class GprofParser(Parser):
for index in self.cycles.iterkeys():
cycles[index] = Cycle()
- for entry in self.functions.itervalues():
+ for entry in compat_itervalues(self.functions):
# populate the function
function = Function(entry.index, entry.name)
function[TIME] = entry.self
@@ -1019,7 +1040,7 @@ class GprofParser(Parser):
profile[TIME] = profile[TIME] + function[TIME]
- for cycle in cycles.itervalues():
+ for cycle in compat_itervalues(cycles):
profile.add_cycle(cycle)
# Compute derived events
@@ -1350,7 +1371,7 @@ class OprofileParser(LineParser):
self.update_subentries_dict(callees_total, callees)
def update_subentries_dict(self, totals, partials):
- for partial in partials.itervalues():
+ for partial in compat_itervalues(partials):
try:
total = totals[partial.id]
except KeyError:
@@ -1372,7 +1393,7 @@ class OprofileParser(LineParser):
# populate the profile
profile[SAMPLES] = 0
- for _callers, _function, _callees in self.entries.itervalues():
+ for _callers, _function, _callees in compat_itervalues(self.entries):
function = Function(_function.id, _function.name)
function[SAMPLES] = _function.samples
profile.add_function(function)
@@ -1384,10 +1405,10 @@ class OprofileParser(LineParser):
function.module = os.path.basename(_function.image)
total_callee_samples = 0
- for _callee in _callees.itervalues():
+ for _callee in compat_itervalues(_callees):
total_callee_samples += _callee.samples
- for _callee in _callees.itervalues():
+ for _callee in compat_itervalues(_callees):
if not _callee.self:
call = Call(_callee.id)
call[SAMPLES2] = _callee.samples
@@ -1548,7 +1569,7 @@ class SysprofParser(XmlParser):
profile = Profile()
profile[SAMPLES] = 0
- for id, object in objects.iteritems():
+ for id, object in compat_iteritems(objects):
# Ignore fake objects (process names, modules, "Everything", "kernel", etc.)
if object['self'] == 0:
continue
@@ -1558,7 +1579,7 @@ class SysprofParser(XmlParser):
profile.add_function(function)
profile[SAMPLES] += function[SAMPLES]
- for id, node in nodes.iteritems():
+ for id, node in compat_iteritems(nodes):
# Ignore fake calls
if node['self'] == 0:
continue
@@ -1672,7 +1693,7 @@ class SharkParser(LineParser):
profile = Profile()
profile[SAMPLES] = 0
- for _function, _callees in self.entries.itervalues():
+ for _function, _callees in compat_itervalues(self.entries):
function = Function(_function.id, _function.name)
function[SAMPLES] = _function.samples
profile.add_function(function)
@@ -1681,7 +1702,7 @@ class SharkParser(LineParser):
if _function.image:
function.module = os.path.basename(_function.image)
- for _callee in _callees.itervalues():
+ for _callee in compat_itervalues(_callees):
call = Call(_callee.id)
call[SAMPLES] = _callee.samples
function.add_call(call)
@@ -1965,7 +1986,8 @@ class PstatsParser:
self.profile = Profile()
self.function_ids = {}
- def get_function_name(self, (filename, line, name)):
+ def get_function_name(self, info):
+ filename, line, name = info
module = os.path.splitext(filename)[0]
module = os.path.basename(module)
return "%s:%d:%s" % (module, line, name)
@@ -1986,14 +2008,14 @@ class PstatsParser:
def parse(self):
self.profile[TIME] = 0.0
self.profile[TOTAL_TIME] = self.stats.total_tt
- for fn, (cc, nc, tt, ct, callers) in self.stats.stats.iteritems():
+ for fn, (cc, nc, tt, ct, callers) in compat_iteritems(self.stats.stats):
callee = self.get_function(fn)
callee.called = nc
callee[TOTAL_TIME] = ct
callee[TIME] = tt
self.profile[TIME] += tt
self.profile[TOTAL_TIME] = max(self.profile[TOTAL_TIME], ct)
- for fn, value in callers.iteritems():
+ for fn, value in compat_iteritems(callers):
caller = self.get_function(fn)
call = Call(callee.id)
if isinstance(value, tuple):
@@ -2190,7 +2212,7 @@ class DotWriter:
self.attr('node', fontname=fontname, shape="box", style="filled", fontcolor="white", width=0, height=0)
self.attr('edge', fontname=fontname)
- for function in profile.functions.itervalues():
+ for function in compat_itervalues(profile.functions):
labels = []
if function.process is not None:
labels.append(function.process)
@@ -2202,7 +2224,7 @@ class DotWriter:
label = event.format(function[event])
labels.append(label)
if function.called is not None:
- labels.append(u"%u\xd7" % (function.called,))
+ labels.append(CALL_TIMES_FORMAT % (function.called,))
if function.weight is not None:
weight = function.weight
@@ -2217,7 +2239,7 @@ class DotWriter:
fontsize = "%.2f" % theme.node_fontsize(weight),
)
- for call in function.calls.itervalues():
+ for call in compat_itervalues(function.calls):
callee = profile.functions[call.callee_id]
labels = []
@@ -2278,7 +2300,7 @@ class DotWriter:
return
self.write(' [')
first = True
- for name, value in attrs.iteritems():
+ for name, value in compat_iteritems(attrs):
if first:
first = False
else:
@@ -2291,7 +2313,7 @@ class DotWriter:
def id(self, id):
if isinstance(id, (int, float)):
s = str(id)
- elif isinstance(id, basestring):
+ elif isinstance(id, compat_basestring):
if id.isalnum() and not id.startswith('0x'):
s = id
else:
@@ -2300,7 +2322,8 @@ class DotWriter:
raise TypeError
self.write(s)
- def color(self, (r, g, b)):
+ def color(self, rgb):
+ r, g, b = rgb
def float2int(f):
if f <= 0.0:
@@ -2312,7 +2335,8 @@ class DotWriter:
return "#" + "".join(["%02x" % float2int(c) for c in (r, g, b)])
def escape(self, s):
- s = s.encode('utf-8')
+ if not PYTHON_3:
+ s = s.encode('utf-8')
s = s.replace('\\', r'\\')
s = s.replace('\n', r'\n')
s = s.replace('\t', r'\t')
@@ -2505,7 +2529,7 @@ class Main:
profile = self.profile
profile.prune(self.options.node_thres/100.0, self.options.edge_thres/100.0)
- for function in profile.functions.itervalues():
+ for function in compat_itervalues(profile.functions):
function.name = self.compress_function_name(function.name)
dot.graph(profile, self.theme)
--
1.7.3.2
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2012-03-15 20:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-15 20:16 [gentoo-commits] gentoo-x86 commit in dev-util/gprof2dot/files: gprof2dot-0_p20100216-python3.patch Sebastian Pipping (sping)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox