diff options
author | Sebastian Pipping <sping@gentoo.org> | 2012-03-15 20:16:55 +0000 |
---|---|---|
committer | Sebastian Pipping <sping@gentoo.org> | 2012-03-15 20:16:55 +0000 |
commit | 0a7b434b157316d3e5c679c587f9f6b87423d4c6 (patch) | |
tree | b576432c4cd1860ec3f80da79ce474b5ff94ad68 | |
parent | Updated sidebar-dotpathsep patch for ignoring trailing path separators, bug #... (diff) | |
download | gentoo-2-0a7b434b157316d3e5c679c587f9f6b87423d4c6.tar.gz gentoo-2-0a7b434b157316d3e5c679c587f9f6b87423d4c6.tar.bz2 gentoo-2-0a7b434b157316d3e5c679c587f9f6b87423d4c6.zip |
dev-util/gprof2dot: Python 3.x (bug #341687)
(Portage version: 2.1.10.49/cvs/Linux x86_64)
-rw-r--r-- | dev-util/gprof2dot/ChangeLog | 8 | ||||
-rw-r--r-- | dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch | 489 | ||||
-rw-r--r-- | dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild | 10 |
3 files changed, 502 insertions, 5 deletions
diff --git a/dev-util/gprof2dot/ChangeLog b/dev-util/gprof2dot/ChangeLog index 4e8580132600..8932e3d7ae19 100644 --- a/dev-util/gprof2dot/ChangeLog +++ b/dev-util/gprof2dot/ChangeLog @@ -1,6 +1,10 @@ # ChangeLog for dev-util/gprof2dot -# Copyright 1999-2010 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/dev-util/gprof2dot/ChangeLog,v 1.3 2010/10/21 00:45:46 sping Exp $ +# Copyright 1999-2012 Gentoo Foundation; Distributed under the GPL v2 +# $Header: /var/cvsroot/gentoo-x86/dev-util/gprof2dot/ChangeLog,v 1.4 2012/03/15 20:16:55 sping Exp $ + + 15 Mar 2012; Sebastian Pipping <sping@gentoo.org> + gprof2dot-0_p20100216.ebuild, +files/gprof2dot-0_p20100216-python3.patch: + Support Python 3.x (bug #341687) 21 Oct 2010; Sebastian Pipping <sping@gentoo.org> gprof2dot-0_p20100216.ebuild: diff --git a/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch b/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch new file mode 100644 index 000000000000..875ccbc1ebd9 --- /dev/null +++ b/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch @@ -0,0 +1,489 @@ +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 + diff --git a/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild b/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild index 91d5a9d40ca2..2f009ab8b3da 100644 --- a/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild +++ b/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild @@ -1,13 +1,13 @@ -# Copyright 1999-2010 Gentoo Foundation +# Copyright 1999-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild,v 1.3 2010/10/21 00:45:46 sping Exp $ +# $Header: /var/cvsroot/gentoo-x86/dev-util/gprof2dot/gprof2dot-0_p20100216.ebuild,v 1.4 2012/03/15 20:16:55 sping Exp $ EAPI="3" SUPPORT_PYTHON_ABIS="1" PYTHON_DEPEND="*" PYTHON_USE_WITH="xml" -inherit python +inherit eutils python DESCRIPTION="Converts profiling output to dot graphs" HOMEPAGE="http://code.google.com/p/jrfonseca/wiki/Gprof2Dot" @@ -21,6 +21,10 @@ IUSE="" DEPEND="" RDEPEND="" +src_prepare() { + epatch "${FILESDIR}"/${P}-python3.patch +} + src_install() { abi_specific_install() { local code_dir="$(python_get_sitedir)"/${PN} |