Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../usr/lib64/python3....
File: pstats.py
"""Class for printing reports on profiled python code."""
[0] Fix | Delete
[1] Fix | Delete
# Written by James Roskind
[2] Fix | Delete
# Based on prior profile module by Sjoerd Mullender...
[3] Fix | Delete
# which was hacked somewhat by: Guido van Rossum
[4] Fix | Delete
[5] Fix | Delete
# Copyright Disney Enterprises, Inc. All Rights Reserved.
[6] Fix | Delete
# Licensed to PSF under a Contributor Agreement
[7] Fix | Delete
#
[8] Fix | Delete
# Licensed under the Apache License, Version 2.0 (the "License");
[9] Fix | Delete
# you may not use this file except in compliance with the License.
[10] Fix | Delete
# You may obtain a copy of the License at
[11] Fix | Delete
#
[12] Fix | Delete
# http://www.apache.org/licenses/LICENSE-2.0
[13] Fix | Delete
#
[14] Fix | Delete
# Unless required by applicable law or agreed to in writing, software
[15] Fix | Delete
# distributed under the License is distributed on an "AS IS" BASIS,
[16] Fix | Delete
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
[17] Fix | Delete
# either express or implied. See the License for the specific language
[18] Fix | Delete
# governing permissions and limitations under the License.
[19] Fix | Delete
[20] Fix | Delete
[21] Fix | Delete
import sys
[22] Fix | Delete
import os
[23] Fix | Delete
import time
[24] Fix | Delete
import marshal
[25] Fix | Delete
import re
[26] Fix | Delete
from enum import Enum
[27] Fix | Delete
from functools import cmp_to_key
[28] Fix | Delete
[29] Fix | Delete
__all__ = ["Stats", "SortKey"]
[30] Fix | Delete
[31] Fix | Delete
[32] Fix | Delete
class SortKey(str, Enum):
[33] Fix | Delete
CALLS = 'calls', 'ncalls'
[34] Fix | Delete
CUMULATIVE = 'cumulative', 'cumtime'
[35] Fix | Delete
FILENAME = 'filename', 'module'
[36] Fix | Delete
LINE = 'line'
[37] Fix | Delete
NAME = 'name'
[38] Fix | Delete
NFL = 'nfl'
[39] Fix | Delete
PCALLS = 'pcalls'
[40] Fix | Delete
STDNAME = 'stdname'
[41] Fix | Delete
TIME = 'time', 'tottime'
[42] Fix | Delete
[43] Fix | Delete
def __new__(cls, *values):
[44] Fix | Delete
value = values[0]
[45] Fix | Delete
obj = str.__new__(cls, value)
[46] Fix | Delete
obj._value_ = value
[47] Fix | Delete
for other_value in values[1:]:
[48] Fix | Delete
cls._value2member_map_[other_value] = obj
[49] Fix | Delete
obj._all_values = values
[50] Fix | Delete
return obj
[51] Fix | Delete
[52] Fix | Delete
[53] Fix | Delete
class Stats:
[54] Fix | Delete
"""This class is used for creating reports from data generated by the
[55] Fix | Delete
Profile class. It is a "friend" of that class, and imports data either
[56] Fix | Delete
by direct access to members of Profile class, or by reading in a dictionary
[57] Fix | Delete
that was emitted (via marshal) from the Profile class.
[58] Fix | Delete
[59] Fix | Delete
The big change from the previous Profiler (in terms of raw functionality)
[60] Fix | Delete
is that an "add()" method has been provided to combine Stats from
[61] Fix | Delete
several distinct profile runs. Both the constructor and the add()
[62] Fix | Delete
method now take arbitrarily many file names as arguments.
[63] Fix | Delete
[64] Fix | Delete
All the print methods now take an argument that indicates how many lines
[65] Fix | Delete
to print. If the arg is a floating point number between 0 and 1.0, then
[66] Fix | Delete
it is taken as a decimal percentage of the available lines to be printed
[67] Fix | Delete
(e.g., .1 means print 10% of all available lines). If it is an integer,
[68] Fix | Delete
it is taken to mean the number of lines of data that you wish to have
[69] Fix | Delete
printed.
[70] Fix | Delete
[71] Fix | Delete
The sort_stats() method now processes some additional options (i.e., in
[72] Fix | Delete
addition to the old -1, 0, 1, or 2 that are respectively interpreted as
[73] Fix | Delete
'stdname', 'calls', 'time', and 'cumulative'). It takes either an
[74] Fix | Delete
arbitrary number of quoted strings or SortKey enum to select the sort
[75] Fix | Delete
order.
[76] Fix | Delete
[77] Fix | Delete
For example sort_stats('time', 'name') or sort_stats(SortKey.TIME,
[78] Fix | Delete
SortKey.NAME) sorts on the major key of 'internal function time', and on
[79] Fix | Delete
the minor key of 'the name of the function'. Look at the two tables in
[80] Fix | Delete
sort_stats() and get_sort_arg_defs(self) for more examples.
[81] Fix | Delete
[82] Fix | Delete
All methods return self, so you can string together commands like:
[83] Fix | Delete
Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
[84] Fix | Delete
print_stats(5).print_callers(5)
[85] Fix | Delete
"""
[86] Fix | Delete
[87] Fix | Delete
def __init__(self, *args, stream=None):
[88] Fix | Delete
self.stream = stream or sys.stdout
[89] Fix | Delete
if not len(args):
[90] Fix | Delete
arg = None
[91] Fix | Delete
else:
[92] Fix | Delete
arg = args[0]
[93] Fix | Delete
args = args[1:]
[94] Fix | Delete
self.init(arg)
[95] Fix | Delete
self.add(*args)
[96] Fix | Delete
[97] Fix | Delete
def init(self, arg):
[98] Fix | Delete
self.all_callees = None # calc only if needed
[99] Fix | Delete
self.files = []
[100] Fix | Delete
self.fcn_list = None
[101] Fix | Delete
self.total_tt = 0
[102] Fix | Delete
self.total_calls = 0
[103] Fix | Delete
self.prim_calls = 0
[104] Fix | Delete
self.max_name_len = 0
[105] Fix | Delete
self.top_level = set()
[106] Fix | Delete
self.stats = {}
[107] Fix | Delete
self.sort_arg_dict = {}
[108] Fix | Delete
self.load_stats(arg)
[109] Fix | Delete
try:
[110] Fix | Delete
self.get_top_level_stats()
[111] Fix | Delete
except Exception:
[112] Fix | Delete
print("Invalid timing data %s" %
[113] Fix | Delete
(self.files[-1] if self.files else ''), file=self.stream)
[114] Fix | Delete
raise
[115] Fix | Delete
[116] Fix | Delete
def load_stats(self, arg):
[117] Fix | Delete
if arg is None:
[118] Fix | Delete
self.stats = {}
[119] Fix | Delete
return
[120] Fix | Delete
elif isinstance(arg, str):
[121] Fix | Delete
with open(arg, 'rb') as f:
[122] Fix | Delete
self.stats = marshal.load(f)
[123] Fix | Delete
try:
[124] Fix | Delete
file_stats = os.stat(arg)
[125] Fix | Delete
arg = time.ctime(file_stats.st_mtime) + " " + arg
[126] Fix | Delete
except: # in case this is not unix
[127] Fix | Delete
pass
[128] Fix | Delete
self.files = [arg]
[129] Fix | Delete
elif hasattr(arg, 'create_stats'):
[130] Fix | Delete
arg.create_stats()
[131] Fix | Delete
self.stats = arg.stats
[132] Fix | Delete
arg.stats = {}
[133] Fix | Delete
if not self.stats:
[134] Fix | Delete
raise TypeError("Cannot create or construct a %r object from %r"
[135] Fix | Delete
% (self.__class__, arg))
[136] Fix | Delete
return
[137] Fix | Delete
[138] Fix | Delete
def get_top_level_stats(self):
[139] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.items():
[140] Fix | Delete
self.total_calls += nc
[141] Fix | Delete
self.prim_calls += cc
[142] Fix | Delete
self.total_tt += tt
[143] Fix | Delete
if ("jprofile", 0, "profiler") in callers:
[144] Fix | Delete
self.top_level.add(func)
[145] Fix | Delete
if len(func_std_string(func)) > self.max_name_len:
[146] Fix | Delete
self.max_name_len = len(func_std_string(func))
[147] Fix | Delete
[148] Fix | Delete
def add(self, *arg_list):
[149] Fix | Delete
if not arg_list:
[150] Fix | Delete
return self
[151] Fix | Delete
for item in reversed(arg_list):
[152] Fix | Delete
if type(self) != type(item):
[153] Fix | Delete
item = Stats(item)
[154] Fix | Delete
self.files += item.files
[155] Fix | Delete
self.total_calls += item.total_calls
[156] Fix | Delete
self.prim_calls += item.prim_calls
[157] Fix | Delete
self.total_tt += item.total_tt
[158] Fix | Delete
for func in item.top_level:
[159] Fix | Delete
self.top_level.add(func)
[160] Fix | Delete
[161] Fix | Delete
if self.max_name_len < item.max_name_len:
[162] Fix | Delete
self.max_name_len = item.max_name_len
[163] Fix | Delete
[164] Fix | Delete
self.fcn_list = None
[165] Fix | Delete
[166] Fix | Delete
for func, stat in item.stats.items():
[167] Fix | Delete
if func in self.stats:
[168] Fix | Delete
old_func_stat = self.stats[func]
[169] Fix | Delete
else:
[170] Fix | Delete
old_func_stat = (0, 0, 0, 0, {},)
[171] Fix | Delete
self.stats[func] = add_func_stats(old_func_stat, stat)
[172] Fix | Delete
return self
[173] Fix | Delete
[174] Fix | Delete
def dump_stats(self, filename):
[175] Fix | Delete
"""Write the profile data to a file we know how to load back."""
[176] Fix | Delete
with open(filename, 'wb') as f:
[177] Fix | Delete
marshal.dump(self.stats, f)
[178] Fix | Delete
[179] Fix | Delete
# list the tuple indices and directions for sorting,
[180] Fix | Delete
# along with some printable description
[181] Fix | Delete
sort_arg_dict_default = {
[182] Fix | Delete
"calls" : (((1,-1), ), "call count"),
[183] Fix | Delete
"ncalls" : (((1,-1), ), "call count"),
[184] Fix | Delete
"cumtime" : (((3,-1), ), "cumulative time"),
[185] Fix | Delete
"cumulative": (((3,-1), ), "cumulative time"),
[186] Fix | Delete
"filename" : (((4, 1), ), "file name"),
[187] Fix | Delete
"line" : (((5, 1), ), "line number"),
[188] Fix | Delete
"module" : (((4, 1), ), "file name"),
[189] Fix | Delete
"name" : (((6, 1), ), "function name"),
[190] Fix | Delete
"nfl" : (((6, 1),(4, 1),(5, 1),), "name/file/line"),
[191] Fix | Delete
"pcalls" : (((0,-1), ), "primitive call count"),
[192] Fix | Delete
"stdname" : (((7, 1), ), "standard name"),
[193] Fix | Delete
"time" : (((2,-1), ), "internal time"),
[194] Fix | Delete
"tottime" : (((2,-1), ), "internal time"),
[195] Fix | Delete
}
[196] Fix | Delete
[197] Fix | Delete
def get_sort_arg_defs(self):
[198] Fix | Delete
"""Expand all abbreviations that are unique."""
[199] Fix | Delete
if not self.sort_arg_dict:
[200] Fix | Delete
self.sort_arg_dict = dict = {}
[201] Fix | Delete
bad_list = {}
[202] Fix | Delete
for word, tup in self.sort_arg_dict_default.items():
[203] Fix | Delete
fragment = word
[204] Fix | Delete
while fragment:
[205] Fix | Delete
if not fragment:
[206] Fix | Delete
break
[207] Fix | Delete
if fragment in dict:
[208] Fix | Delete
bad_list[fragment] = 0
[209] Fix | Delete
break
[210] Fix | Delete
dict[fragment] = tup
[211] Fix | Delete
fragment = fragment[:-1]
[212] Fix | Delete
for word in bad_list:
[213] Fix | Delete
del dict[word]
[214] Fix | Delete
return self.sort_arg_dict
[215] Fix | Delete
[216] Fix | Delete
def sort_stats(self, *field):
[217] Fix | Delete
if not field:
[218] Fix | Delete
self.fcn_list = 0
[219] Fix | Delete
return self
[220] Fix | Delete
if len(field) == 1 and isinstance(field[0], int):
[221] Fix | Delete
# Be compatible with old profiler
[222] Fix | Delete
field = [ {-1: "stdname",
[223] Fix | Delete
0: "calls",
[224] Fix | Delete
1: "time",
[225] Fix | Delete
2: "cumulative"}[field[0]] ]
[226] Fix | Delete
elif len(field) >= 2:
[227] Fix | Delete
for arg in field[1:]:
[228] Fix | Delete
if type(arg) != type(field[0]):
[229] Fix | Delete
raise TypeError("Can't have mixed argument type")
[230] Fix | Delete
[231] Fix | Delete
sort_arg_defs = self.get_sort_arg_defs()
[232] Fix | Delete
[233] Fix | Delete
sort_tuple = ()
[234] Fix | Delete
self.sort_type = ""
[235] Fix | Delete
connector = ""
[236] Fix | Delete
for word in field:
[237] Fix | Delete
if isinstance(word, SortKey):
[238] Fix | Delete
word = word.value
[239] Fix | Delete
sort_tuple = sort_tuple + sort_arg_defs[word][0]
[240] Fix | Delete
self.sort_type += connector + sort_arg_defs[word][1]
[241] Fix | Delete
connector = ", "
[242] Fix | Delete
[243] Fix | Delete
stats_list = []
[244] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.items():
[245] Fix | Delete
stats_list.append((cc, nc, tt, ct) + func +
[246] Fix | Delete
(func_std_string(func), func))
[247] Fix | Delete
[248] Fix | Delete
stats_list.sort(key=cmp_to_key(TupleComp(sort_tuple).compare))
[249] Fix | Delete
[250] Fix | Delete
self.fcn_list = fcn_list = []
[251] Fix | Delete
for tuple in stats_list:
[252] Fix | Delete
fcn_list.append(tuple[-1])
[253] Fix | Delete
return self
[254] Fix | Delete
[255] Fix | Delete
def reverse_order(self):
[256] Fix | Delete
if self.fcn_list:
[257] Fix | Delete
self.fcn_list.reverse()
[258] Fix | Delete
return self
[259] Fix | Delete
[260] Fix | Delete
def strip_dirs(self):
[261] Fix | Delete
oldstats = self.stats
[262] Fix | Delete
self.stats = newstats = {}
[263] Fix | Delete
max_name_len = 0
[264] Fix | Delete
for func, (cc, nc, tt, ct, callers) in oldstats.items():
[265] Fix | Delete
newfunc = func_strip_path(func)
[266] Fix | Delete
if len(func_std_string(newfunc)) > max_name_len:
[267] Fix | Delete
max_name_len = len(func_std_string(newfunc))
[268] Fix | Delete
newcallers = {}
[269] Fix | Delete
for func2, caller in callers.items():
[270] Fix | Delete
newcallers[func_strip_path(func2)] = caller
[271] Fix | Delete
[272] Fix | Delete
if newfunc in newstats:
[273] Fix | Delete
newstats[newfunc] = add_func_stats(
[274] Fix | Delete
newstats[newfunc],
[275] Fix | Delete
(cc, nc, tt, ct, newcallers))
[276] Fix | Delete
else:
[277] Fix | Delete
newstats[newfunc] = (cc, nc, tt, ct, newcallers)
[278] Fix | Delete
old_top = self.top_level
[279] Fix | Delete
self.top_level = new_top = set()
[280] Fix | Delete
for func in old_top:
[281] Fix | Delete
new_top.add(func_strip_path(func))
[282] Fix | Delete
[283] Fix | Delete
self.max_name_len = max_name_len
[284] Fix | Delete
[285] Fix | Delete
self.fcn_list = None
[286] Fix | Delete
self.all_callees = None
[287] Fix | Delete
return self
[288] Fix | Delete
[289] Fix | Delete
def calc_callees(self):
[290] Fix | Delete
if self.all_callees:
[291] Fix | Delete
return
[292] Fix | Delete
self.all_callees = all_callees = {}
[293] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.items():
[294] Fix | Delete
if not func in all_callees:
[295] Fix | Delete
all_callees[func] = {}
[296] Fix | Delete
for func2, caller in callers.items():
[297] Fix | Delete
if not func2 in all_callees:
[298] Fix | Delete
all_callees[func2] = {}
[299] Fix | Delete
all_callees[func2][func] = caller
[300] Fix | Delete
return
[301] Fix | Delete
[302] Fix | Delete
#******************************************************************
[303] Fix | Delete
# The following functions support actual printing of reports
[304] Fix | Delete
#******************************************************************
[305] Fix | Delete
[306] Fix | Delete
# Optional "amount" is either a line count, or a percentage of lines.
[307] Fix | Delete
[308] Fix | Delete
def eval_print_amount(self, sel, list, msg):
[309] Fix | Delete
new_list = list
[310] Fix | Delete
if isinstance(sel, str):
[311] Fix | Delete
try:
[312] Fix | Delete
rex = re.compile(sel)
[313] Fix | Delete
except re.error:
[314] Fix | Delete
msg += " <Invalid regular expression %r>\n" % sel
[315] Fix | Delete
return new_list, msg
[316] Fix | Delete
new_list = []
[317] Fix | Delete
for func in list:
[318] Fix | Delete
if rex.search(func_std_string(func)):
[319] Fix | Delete
new_list.append(func)
[320] Fix | Delete
else:
[321] Fix | Delete
count = len(list)
[322] Fix | Delete
if isinstance(sel, float) and 0.0 <= sel < 1.0:
[323] Fix | Delete
count = int(count * sel + .5)
[324] Fix | Delete
new_list = list[:count]
[325] Fix | Delete
elif isinstance(sel, int) and 0 <= sel < count:
[326] Fix | Delete
count = sel
[327] Fix | Delete
new_list = list[:count]
[328] Fix | Delete
if len(list) != len(new_list):
[329] Fix | Delete
msg += " List reduced from %r to %r due to restriction <%r>\n" % (
[330] Fix | Delete
len(list), len(new_list), sel)
[331] Fix | Delete
[332] Fix | Delete
return new_list, msg
[333] Fix | Delete
[334] Fix | Delete
def get_print_list(self, sel_list):
[335] Fix | Delete
width = self.max_name_len
[336] Fix | Delete
if self.fcn_list:
[337] Fix | Delete
stat_list = self.fcn_list[:]
[338] Fix | Delete
msg = " Ordered by: " + self.sort_type + '\n'
[339] Fix | Delete
else:
[340] Fix | Delete
stat_list = list(self.stats.keys())
[341] Fix | Delete
msg = " Random listing order was used\n"
[342] Fix | Delete
[343] Fix | Delete
for selection in sel_list:
[344] Fix | Delete
stat_list, msg = self.eval_print_amount(selection, stat_list, msg)
[345] Fix | Delete
[346] Fix | Delete
count = len(stat_list)
[347] Fix | Delete
[348] Fix | Delete
if not stat_list:
[349] Fix | Delete
return 0, stat_list
[350] Fix | Delete
print(msg, file=self.stream)
[351] Fix | Delete
if count < len(self.stats):
[352] Fix | Delete
width = 0
[353] Fix | Delete
for func in stat_list:
[354] Fix | Delete
if len(func_std_string(func)) > width:
[355] Fix | Delete
width = len(func_std_string(func))
[356] Fix | Delete
return width+2, stat_list
[357] Fix | Delete
[358] Fix | Delete
def print_stats(self, *amount):
[359] Fix | Delete
for filename in self.files:
[360] Fix | Delete
print(filename, file=self.stream)
[361] Fix | Delete
if self.files:
[362] Fix | Delete
print(file=self.stream)
[363] Fix | Delete
indent = ' ' * 8
[364] Fix | Delete
for func in self.top_level:
[365] Fix | Delete
print(indent, func_get_function_name(func), file=self.stream)
[366] Fix | Delete
[367] Fix | Delete
print(indent, self.total_calls, "function calls", end=' ', file=self.stream)
[368] Fix | Delete
if self.total_calls != self.prim_calls:
[369] Fix | Delete
print("(%d primitive calls)" % self.prim_calls, end=' ', file=self.stream)
[370] Fix | Delete
print("in %.3f seconds" % self.total_tt, file=self.stream)
[371] Fix | Delete
print(file=self.stream)
[372] Fix | Delete
width, list = self.get_print_list(amount)
[373] Fix | Delete
if list:
[374] Fix | Delete
self.print_title()
[375] Fix | Delete
for func in list:
[376] Fix | Delete
self.print_line(func)
[377] Fix | Delete
print(file=self.stream)
[378] Fix | Delete
print(file=self.stream)
[379] Fix | Delete
return self
[380] Fix | Delete
[381] Fix | Delete
def print_callees(self, *amount):
[382] Fix | Delete
width, list = self.get_print_list(amount)
[383] Fix | Delete
if list:
[384] Fix | Delete
self.calc_callees()
[385] Fix | Delete
[386] Fix | Delete
self.print_call_heading(width, "called...")
[387] Fix | Delete
for func in list:
[388] Fix | Delete
if func in self.all_callees:
[389] Fix | Delete
self.print_call_line(width, func, self.all_callees[func])
[390] Fix | Delete
else:
[391] Fix | Delete
self.print_call_line(width, func, {})
[392] Fix | Delete
print(file=self.stream)
[393] Fix | Delete
print(file=self.stream)
[394] Fix | Delete
return self
[395] Fix | Delete
[396] Fix | Delete
def print_callers(self, *amount):
[397] Fix | Delete
width, list = self.get_print_list(amount)
[398] Fix | Delete
if list:
[399] Fix | Delete
self.print_call_heading(width, "was called by...")
[400] Fix | Delete
for func in list:
[401] Fix | Delete
cc, nc, tt, ct, callers = self.stats[func]
[402] Fix | Delete
self.print_call_line(width, func, callers, "<-")
[403] Fix | Delete
print(file=self.stream)
[404] Fix | Delete
print(file=self.stream)
[405] Fix | Delete
return self
[406] Fix | Delete
[407] Fix | Delete
def print_call_heading(self, name_size, column_title):
[408] Fix | Delete
print("Function ".ljust(name_size) + column_title, file=self.stream)
[409] Fix | Delete
# print sub-header only if we have new-style callers
[410] Fix | Delete
subheader = False
[411] Fix | Delete
for cc, nc, tt, ct, callers in self.stats.values():
[412] Fix | Delete
if callers:
[413] Fix | Delete
value = next(iter(callers.values()))
[414] Fix | Delete
subheader = isinstance(value, tuple)
[415] Fix | Delete
break
[416] Fix | Delete
if subheader:
[417] Fix | Delete
print(" "*name_size + " ncalls tottime cumtime", file=self.stream)
[418] Fix | Delete
[419] Fix | Delete
def print_call_line(self, name_size, source, call_dict, arrow="->"):
[420] Fix | Delete
print(func_std_string(source).ljust(name_size) + arrow, end=' ', file=self.stream)
[421] Fix | Delete
if not call_dict:
[422] Fix | Delete
print(file=self.stream)
[423] Fix | Delete
return
[424] Fix | Delete
clist = sorted(call_dict.keys())
[425] Fix | Delete
indent = ""
[426] Fix | Delete
for func in clist:
[427] Fix | Delete
name = func_std_string(func)
[428] Fix | Delete
value = call_dict[func]
[429] Fix | Delete
if isinstance(value, tuple):
[430] Fix | Delete
nc, cc, tt, ct = value
[431] Fix | Delete
if nc != cc:
[432] Fix | Delete
substats = '%d/%d' % (nc, cc)
[433] Fix | Delete
else:
[434] Fix | Delete
substats = '%d' % (nc,)
[435] Fix | Delete
substats = '%s %s %s %s' % (substats.rjust(7+2*len(indent)),
[436] Fix | Delete
f8(tt), f8(ct), name)
[437] Fix | Delete
left_width = name_size + 1
[438] Fix | Delete
else:
[439] Fix | Delete
substats = '%s(%r) %s' % (name, value, f8(self.stats[func][3]))
[440] Fix | Delete
left_width = name_size + 3
[441] Fix | Delete
print(indent*left_width + substats, file=self.stream)
[442] Fix | Delete
indent = " "
[443] Fix | Delete
[444] Fix | Delete
def print_title(self):
[445] Fix | Delete
print(' ncalls tottime percall cumtime percall', end=' ', file=self.stream)
[446] Fix | Delete
print('filename:lineno(function)', file=self.stream)
[447] Fix | Delete
[448] Fix | Delete
def print_line(self, func): # hack: should print percentages
[449] Fix | Delete
cc, nc, tt, ct, callers = self.stats[func]
[450] Fix | Delete
c = str(nc)
[451] Fix | Delete
if nc != cc:
[452] Fix | Delete
c = c + '/' + str(cc)
[453] Fix | Delete
print(c.rjust(9), end=' ', file=self.stream)
[454] Fix | Delete
print(f8(tt), end=' ', file=self.stream)
[455] Fix | Delete
if nc == 0:
[456] Fix | Delete
print(' '*8, end=' ', file=self.stream)
[457] Fix | Delete
else:
[458] Fix | Delete
print(f8(tt/nc), end=' ', file=self.stream)
[459] Fix | Delete
print(f8(ct), end=' ', file=self.stream)
[460] Fix | Delete
if cc == 0:
[461] Fix | Delete
print(' '*8, end=' ', file=self.stream)
[462] Fix | Delete
else:
[463] Fix | Delete
print(f8(ct/cc), end=' ', file=self.stream)
[464] Fix | Delete
print(func_std_string(func), file=self.stream)
[465] Fix | Delete
[466] Fix | Delete
class TupleComp:
[467] Fix | Delete
"""This class provides a generic function for comparing any two tuples.
[468] Fix | Delete
Each instance records a list of tuple-indices (from most significant
[469] Fix | Delete
to least significant), and sort direction (ascending or decending) for
[470] Fix | Delete
each tuple-index. The compare functions can then be used as the function
[471] Fix | Delete
argument to the system sort() function when a list of tuples need to be
[472] Fix | Delete
sorted in the instances order."""
[473] Fix | Delete
[474] Fix | Delete
def __init__(self, comp_select_list):
[475] Fix | Delete
self.comp_select_list = comp_select_list
[476] Fix | Delete
[477] Fix | Delete
def compare (self, left, right):
[478] Fix | Delete
for index, direction in self.comp_select_list:
[479] Fix | Delete
l = left[index]
[480] Fix | Delete
r = right[index]
[481] Fix | Delete
if l < r:
[482] Fix | Delete
return -direction
[483] Fix | Delete
if l > r:
[484] Fix | Delete
return direction
[485] Fix | Delete
return 0
[486] Fix | Delete
[487] Fix | Delete
[488] Fix | Delete
#**************************************************************************
[489] Fix | Delete
# func_name is a triple (file:string, line:int, name:string)
[490] Fix | Delete
[491] Fix | Delete
def func_strip_path(func_name):
[492] Fix | Delete
filename, line, name = func_name
[493] Fix | Delete
return os.path.basename(filename), line, name
[494] Fix | Delete
[495] Fix | Delete
def func_get_function_name(func):
[496] Fix | Delete
return func[2]
[497] Fix | Delete
[498] Fix | Delete
def func_std_string(func_name): # match what old profile produced
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function