Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 253305 Details for
Bug 341687
[PATCH] dev-util/gprof2dot and Python3
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
First try on a patch for Python 3 (without breaking Python 2)
0001-Support-both-Python-2.x-and-3.x.patch (text/plain), 20.39 KB, created by
Sebastian Pipping
on 2010-11-05 17:14:01 UTC
(
hide
)
Description:
First try on a patch for Python 3 (without breaking Python 2)
Filename:
MIME Type:
Creator:
Sebastian Pipping
Created:
2010-11-05 17:14:01 UTC
Size:
20.39 KB
patch
obsolete
>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 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 341687
: 253305