home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_677 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  20.4 KB  |  699 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import sys
  5. import os
  6. import time
  7. import marshal
  8. import re
  9. __all__ = [
  10.     'Stats']
  11.  
  12. class Stats:
  13.     
  14.     def __init__(self, *args, **kwds):
  15.         self.stream = sys.stdout
  16.         if 'stream' in kwds:
  17.             self.stream = kwds['stream']
  18.             del kwds['stream']
  19.         
  20.         if kwds:
  21.             keys = kwds.keys()
  22.             keys.sort()
  23.             extras = []([ '%s=%s' % (k, kwds[k]) for k in keys ])
  24.             raise ValueError, 'unrecognized keyword args: %s' % extras
  25.         kwds
  26.         if not len(args):
  27.             arg = None
  28.         else:
  29.             arg = args[0]
  30.             args = args[1:]
  31.         self.init(arg)
  32.         self.add(*args)
  33.  
  34.     
  35.     def init(self, arg):
  36.         self.all_callees = None
  37.         self.files = []
  38.         self.fcn_list = None
  39.         self.total_tt = 0
  40.         self.total_calls = 0
  41.         self.prim_calls = 0
  42.         self.max_name_len = 0
  43.         self.top_level = { }
  44.         self.stats = { }
  45.         self.sort_arg_dict = { }
  46.         self.load_stats(arg)
  47.         trouble = 1
  48.         
  49.         try:
  50.             self.get_top_level_stats()
  51.             trouble = 0
  52.         finally:
  53.             pass
  54.  
  55.  
  56.     
  57.     def load_stats(self, arg):
  58.         if not arg:
  59.             self.stats = { }
  60.         elif isinstance(arg, basestring):
  61.             f = open(arg, 'rb')
  62.             self.stats = marshal.load(f)
  63.             f.close()
  64.             
  65.             try:
  66.                 file_stats = os.stat(arg)
  67.                 arg = time.ctime(file_stats.st_mtime) + '    ' + arg
  68.             except:
  69.                 pass
  70.  
  71.             self.files = [
  72.                 arg]
  73.         elif hasattr(arg, 'create_stats'):
  74.             arg.create_stats()
  75.             self.stats = arg.stats
  76.             arg.stats = { }
  77.         
  78.         if not self.stats:
  79.             raise TypeError, "Cannot create or construct a %r object from '%r''" % (self.__class__, arg)
  80.         self.stats
  81.  
  82.     
  83.     def get_top_level_stats(self):
  84.         for cc, nc, tt, ct, callers in self.stats.items():
  85.             self.total_calls += nc
  86.             self.prim_calls += cc
  87.             self.total_tt += tt
  88.             if len(func_std_string(func)) > self.max_name_len:
  89.                 self.max_name_len = len(func_std_string(func))
  90.                 continue
  91.             self if ('jprofile', 0, 'profiler') in callers else self
  92.         
  93.  
  94.     
  95.     def add(self, *arg_list):
  96.         if not arg_list:
  97.             return self
  98.         if len(arg_list) > 1:
  99.             self.add(*arg_list[1:])
  100.         
  101.         other = arg_list[0]
  102.         if type(self) != type(other) or self.__class__ != other.__class__:
  103.             other = Stats(other)
  104.         
  105.         self.files += other.files
  106.         self.total_calls += other.total_calls
  107.         self.prim_calls += other.prim_calls
  108.         self.total_tt += other.total_tt
  109.         for func in other.top_level:
  110.             self.top_level[func] = None
  111.         
  112.         self.fcn_list = None
  113.         for func, stat in other.stats.iteritems():
  114.             self.stats[func] = add_func_stats(old_func_stat, stat)
  115.         
  116.         return self
  117.  
  118.     
  119.     def dump_stats(self, filename):
  120.         f = file(filename, 'wb')
  121.         
  122.         try:
  123.             marshal.dump(self.stats, f)
  124.         finally:
  125.             f.close()
  126.  
  127.  
  128.     sort_arg_dict_default = {
  129.         'calls': (((1, -1),), 'call count'),
  130.         'cumulative': (((3, -1),), 'cumulative time'),
  131.         'file': (((4, 1),), 'file name'),
  132.         'line': (((5, 1),), 'line number'),
  133.         'module': (((4, 1),), 'file name'),
  134.         'name': (((6, 1),), 'function name'),
  135.         'nfl': (((6, 1), (4, 1), (5, 1)), 'name/file/line'),
  136.         'pcalls': (((0, -1),), 'call count'),
  137.         'stdname': (((7, 1),), 'standard name'),
  138.         'time': (((2, -1),), 'internal time') }
  139.     
  140.     def get_sort_arg_defs(self):
  141.         if not self.sort_arg_dict:
  142.             self.sort_arg_dict = dict = { }
  143.             bad_list = { }
  144.             for word, tup in self.sort_arg_dict_default.iteritems():
  145.                 fragment = word
  146.                 while fragment:
  147.                     if not fragment:
  148.                         break
  149.                     
  150.                     if fragment in dict:
  151.                         bad_list[fragment] = 0
  152.                         break
  153.                     
  154.                     dict[fragment] = tup
  155.                     fragment = fragment[:-1]
  156.             
  157.             for word in bad_list:
  158.                 del dict[word]
  159.             
  160.         
  161.         return self.sort_arg_dict
  162.  
  163.     
  164.     def sort_stats(self, *field):
  165.         if not field:
  166.             self.fcn_list = 0
  167.             return self
  168.         if len(field) == 1 and type(field[0]) == type(1):
  169.             field = [
  170.                 {
  171.                     -1: 'stdname',
  172.                     0: 'calls',
  173.                     1: 'time',
  174.                     2: 'cumulative' }[field[0]]]
  175.         
  176.         sort_arg_defs = self.get_sort_arg_defs()
  177.         sort_tuple = ()
  178.         self.sort_type = ''
  179.         connector = ''
  180.         for word in field:
  181.             sort_tuple = sort_tuple + sort_arg_defs[word][0]
  182.             self.sort_type += connector + sort_arg_defs[word][1]
  183.             connector = ', '
  184.         
  185.         stats_list = []
  186.         for cc, nc, tt, ct, callers in self.stats.iteritems():
  187.             stats_list.append((cc, nc, tt, ct) + func + (func_std_string(func), func))
  188.         
  189.         stats_list.sort(key = CmpToKey(TupleComp(sort_tuple).compare))
  190.         self.fcn_list = fcn_list = []
  191.         for tuple in stats_list:
  192.             fcn_list.append(tuple[-1])
  193.         
  194.         return self
  195.  
  196.     
  197.     def reverse_order(self):
  198.         if self.fcn_list:
  199.             self.fcn_list.reverse()
  200.         
  201.         return self
  202.  
  203.     
  204.     def strip_dirs(self):
  205.         oldstats = self.stats
  206.         self.stats = newstats = { }
  207.         max_name_len = 0
  208.         for cc, nc, tt, ct, callers in oldstats.iteritems():
  209.             newfunc = func_strip_path(func)
  210.             if len(func_std_string(newfunc)) > max_name_len:
  211.                 max_name_len = len(func_std_string(newfunc))
  212.             
  213.             newcallers = { }
  214.             for func2, caller in callers.iteritems():
  215.                 newcallers[func_strip_path(func2)] = caller
  216.             
  217.             if newfunc in newstats:
  218.                 newstats[newfunc] = add_func_stats(newstats[newfunc], (cc, nc, tt, ct, newcallers))
  219.                 continue
  220.             newstats[newfunc] = (cc, nc, tt, ct, newcallers)
  221.         
  222.         old_top = self.top_level
  223.         self.top_level = new_top = { }
  224.         for func in old_top:
  225.             new_top[func_strip_path(func)] = None
  226.         
  227.         self.max_name_len = max_name_len
  228.         self.fcn_list = None
  229.         self.all_callees = None
  230.         return self
  231.  
  232.     
  233.     def calc_callees(self):
  234.         if self.all_callees:
  235.             return None
  236.         for cc, nc, tt, ct, callers in self.stats.iteritems():
  237.             for func2, caller in callers.iteritems():
  238.                 if func2 not in all_callees:
  239.                     all_callees[func2] = { }
  240.                 
  241.                 all_callees[func2][func] = caller
  242.             
  243.         
  244.  
  245.     
  246.     def eval_print_amount(self, sel, list, msg):
  247.         new_list = list
  248.         if type(sel) == type(''):
  249.             new_list = []
  250.             for func in list:
  251.                 if re.search(sel, func_std_string(func)):
  252.                     new_list.append(func)
  253.                     continue
  254.             
  255.         else:
  256.             count = len(list)
  257.             if type(sel) == type(1):
  258.                 if sel <= sel:
  259.                     pass
  260.                 elif sel < 1:
  261.                     count = int(count * sel + 0.5)
  262.                     new_list = list[:count]
  263.                 elif type(sel) == type(1):
  264.                     if sel <= sel:
  265.                         pass
  266.                     elif sel < count:
  267.                         count = sel
  268.                         new_list = list[:count]
  269.                     
  270.         if len(list) != len(new_list):
  271.             msg = msg + '   List reduced from %r to %r due to restriction <%r>\n' % (len(list), len(new_list), sel)
  272.         
  273.         return (new_list, msg)
  274.  
  275.     
  276.     def get_print_list(self, sel_list):
  277.         width = self.max_name_len
  278.         if self.fcn_list:
  279.             list = self.fcn_list[:]
  280.             msg = '   Ordered by: ' + self.sort_type + '\n'
  281.         else:
  282.             list = self.stats.keys()
  283.             msg = '   Random listing order was used\n'
  284.         for selection in sel_list:
  285.             (list, msg) = self.eval_print_amount(selection, list, msg)
  286.         
  287.         count = len(list)
  288.         if not list:
  289.             return (0, list)
  290.         print >>self.stream, msg
  291.         if count < len(self.stats):
  292.             width = 0
  293.             for func in list:
  294.                 if len(func_std_string(func)) > width:
  295.                     width = len(func_std_string(func))
  296.                     continue
  297.             
  298.         
  299.         return (width + 2, list)
  300.  
  301.     
  302.     def print_stats(self, *amount):
  303.         for filename in self.files:
  304.             print >>self.stream, filename
  305.         
  306.         if self.files:
  307.             print >>self.stream
  308.         
  309.         indent = '        '
  310.         for func in self.top_level:
  311.             print >>self.stream, indent, func_get_function_name(func)
  312.         
  313.         print >>self.stream, indent, self.total_calls, 'function calls',
  314.         if self.total_calls != self.prim_calls:
  315.             print >>self.stream, '(%d primitive calls)' % self.prim_calls,
  316.         
  317.         print >>self.stream, 'in %.3f CPU seconds' % self.total_tt
  318.         print >>self.stream
  319.         (width, list) = self.get_print_list(amount)
  320.         if list:
  321.             self.print_title()
  322.             for func in list:
  323.                 self.print_line(func)
  324.             
  325.             print >>self.stream
  326.             print >>self.stream
  327.         
  328.         return self
  329.  
  330.     
  331.     def print_callees(self, *amount):
  332.         (width, list) = self.get_print_list(amount)
  333.         if list:
  334.             self.calc_callees()
  335.             self.print_call_heading(width, 'called...')
  336.             for func in list:
  337.                 if func in self.all_callees:
  338.                     self.print_call_line(width, func, self.all_callees[func])
  339.                     continue
  340.                 self.print_call_line(width, func, { })
  341.             
  342.             print >>self.stream
  343.             print >>self.stream
  344.         
  345.         return self
  346.  
  347.     
  348.     def print_callers(self, *amount):
  349.         (width, list) = self.get_print_list(amount)
  350.         if list:
  351.             self.print_call_heading(width, 'was called by...')
  352.             for func in list:
  353.                 (cc, nc, tt, ct, callers) = self.stats[func]
  354.                 self.print_call_line(width, func, callers, '<-')
  355.             
  356.             print >>self.stream
  357.             print >>self.stream
  358.         
  359.         return self
  360.  
  361.     
  362.     def print_call_heading(self, name_size, column_title):
  363.         print >>self.stream, 'Function '.ljust(name_size) + column_title
  364.         subheader = False
  365.         for cc, nc, tt, ct, callers in self.stats.itervalues():
  366.             if callers:
  367.                 value = callers.itervalues().next()
  368.                 subheader = isinstance(value, tuple)
  369.                 break
  370.                 continue
  371.         
  372.         if subheader:
  373.             print >>self.stream, ' ' * name_size + '    ncalls  tottime  cumtime'
  374.         
  375.  
  376.     
  377.     def print_call_line(self, name_size, source, call_dict, arrow = '->'):
  378.         print >>self.stream, func_std_string(source).ljust(name_size) + arrow,
  379.         if not call_dict:
  380.             print >>self.stream
  381.             return None
  382.         clist = call_dict.keys()
  383.         clist.sort()
  384.         indent = ''
  385.         for func in clist:
  386.             name = func_std_string(func)
  387.             value = call_dict[func]
  388.             print >>self.stream, indent * left_width + substats
  389.             indent = ' '
  390.         
  391.  
  392.     
  393.     def print_title(self):
  394.         print >>self.stream, '   ncalls  tottime  percall  cumtime  percall',
  395.         print >>self.stream, 'filename:lineno(function)'
  396.  
  397.     
  398.     def print_line(self, func):
  399.         (cc, nc, tt, ct, callers) = self.stats[func]
  400.         c = str(nc)
  401.         if nc != cc:
  402.             c = c + '/' + str(cc)
  403.         
  404.         print >>self.stream, c.rjust(9),
  405.         print >>self.stream, f8(tt),
  406.         if nc == 0:
  407.             print >>self.stream, '        ',
  408.         else:
  409.             print >>self.stream, f8(tt / nc),
  410.         print >>self.stream, f8(ct),
  411.         if cc == 0:
  412.             print >>self.stream, '        ',
  413.         else:
  414.             print >>self.stream, f8(ct / cc),
  415.         print >>self.stream, func_std_string(func)
  416.  
  417.  
  418.  
  419. class TupleComp:
  420.     
  421.     def __init__(self, comp_select_list):
  422.         self.comp_select_list = comp_select_list
  423.  
  424.     
  425.     def compare(self, left, right):
  426.         for index, direction in self.comp_select_list:
  427.             l = left[index]
  428.             r = right[index]
  429.             if l < r:
  430.                 return -direction
  431.             if l > r:
  432.                 return direction
  433.         
  434.         return 0
  435.  
  436.  
  437.  
  438. def CmpToKey(mycmp):
  439.     
  440.     class K((object,)):
  441.         
  442.         def __init__(self, obj):
  443.             self.obj = obj
  444.  
  445.         
  446.         def __lt__(self, other):
  447.             return mycmp(self.obj, other.obj) == -1
  448.  
  449.  
  450.     return K
  451.  
  452.  
  453. def func_strip_path(func_name):
  454.     (filename, line, name) = func_name
  455.     return (os.path.basename(filename), line, name)
  456.  
  457.  
  458. def func_get_function_name(func):
  459.     return func[2]
  460.  
  461.  
  462. def func_std_string(func_name):
  463.     if func_name[:2] == ('~', 0):
  464.         name = func_name[2]
  465.         if name.startswith('<') and name.endswith('>'):
  466.             return '{%s}' % name[1:-1]
  467.         return name
  468.     func_name[:2] == ('~', 0)
  469.     return '%s:%d(%s)' % func_name
  470.  
  471.  
  472. def add_func_stats(target, source):
  473.     (cc, nc, tt, ct, callers) = source
  474.     (t_cc, t_nc, t_tt, t_ct, t_callers) = target
  475.     return (cc + t_cc, nc + t_nc, tt + t_tt, ct + t_ct, add_callers(t_callers, callers))
  476.  
  477.  
  478. def add_callers(target, source):
  479.     new_callers = { }
  480.     for func, caller in target.iteritems():
  481.         new_callers[func] = caller
  482.     
  483.     for func, caller in source.iteritems():
  484.         if func in new_callers:
  485.             new_callers[func] = []([ i[0] + i[1] for i in zip(caller, new_callers[func]) ])
  486.             continue
  487.         []
  488.         new_callers[func] = caller
  489.     
  490.     return new_callers
  491.  
  492.  
  493. def count_calls(callers):
  494.     nc = 0
  495.     for calls in callers.itervalues():
  496.         nc += calls
  497.     
  498.     return nc
  499.  
  500.  
  501. def f8(x):
  502.     return '%8.3f' % x
  503.  
  504. if __name__ == '__main__':
  505.     import cmd
  506.     
  507.     try:
  508.         import readline
  509.     except ImportError:
  510.         pass
  511.  
  512.     
  513.     class ProfileBrowser(cmd.Cmd):
  514.         
  515.         def __init__(self, profile = None):
  516.             cmd.Cmd.__init__(self)
  517.             self.prompt = '% '
  518.             if profile is not None:
  519.                 self.stats = Stats(profile)
  520.                 self.stream = self.stats.stream
  521.             else:
  522.                 self.stats = None
  523.                 self.stream = sys.stdout
  524.  
  525.         
  526.         def generic(self, fn, line):
  527.             args = line.split()
  528.             processed = []
  529.             for term in args:
  530.                 
  531.                 try:
  532.                     processed.append(int(term))
  533.                 except ValueError:
  534.                     pass
  535.  
  536.                 
  537.                 try:
  538.                     frac = float(term)
  539.                     if frac > 1 or frac < 0:
  540.                         print >>self.stream, 'Fraction argument must be in [0, 1]'
  541.                         continue
  542.                     
  543.                     processed.append(frac)
  544.                 except ValueError:
  545.                     pass
  546.  
  547.                 processed.append(term)
  548.             
  549.             if self.stats:
  550.                 getattr(self.stats, fn)(*processed)
  551.             else:
  552.                 print >>self.stream, 'No statistics object is loaded.'
  553.             return 0
  554.  
  555.         
  556.         def generic_help(self):
  557.             print >>self.stream, 'Arguments may be:'
  558.             print >>self.stream, '* An integer maximum number of entries to print.'
  559.             print >>self.stream, '* A decimal fractional number between 0 and 1, controlling'
  560.             print >>self.stream, '  what fraction of selected entries to print.'
  561.             print >>self.stream, '* A regular expression; only entries with function names'
  562.             print >>self.stream, '  that match it are printed.'
  563.  
  564.         
  565.         def do_add(self, line):
  566.             self.stats.add(line)
  567.             return 0
  568.  
  569.         
  570.         def help_add(self):
  571.             print >>self.stream, 'Add profile info from given file to current statistics object.'
  572.  
  573.         
  574.         def do_callees(self, line):
  575.             return self.generic('print_callees', line)
  576.  
  577.         
  578.         def help_callees(self):
  579.             print >>self.stream, 'Print callees statistics from the current stat object.'
  580.             self.generic_help()
  581.  
  582.         
  583.         def do_callers(self, line):
  584.             return self.generic('print_callers', line)
  585.  
  586.         
  587.         def help_callers(self):
  588.             print >>self.stream, 'Print callers statistics from the current stat object.'
  589.             self.generic_help()
  590.  
  591.         
  592.         def do_EOF(self, line):
  593.             print >>self.stream, ''
  594.             return 1
  595.  
  596.         
  597.         def help_EOF(self):
  598.             print >>self.stream, 'Leave the profile brower.'
  599.  
  600.         
  601.         def do_quit(self, line):
  602.             return 1
  603.  
  604.         
  605.         def help_quit(self):
  606.             print >>self.stream, 'Leave the profile brower.'
  607.  
  608.         
  609.         def do_read(self, line):
  610.             if line:
  611.                 
  612.                 try:
  613.                     self.stats = Stats(line)
  614.                 except IOError:
  615.                     args = None
  616.                     print >>self.stream, args[1]
  617.                     return None
  618.  
  619.                 self.prompt = line + '% '
  620.             elif len(self.prompt) > 2:
  621.                 line = self.prompt[-2:]
  622.             else:
  623.                 print >>self.stream, 'No statistics object is current -- cannot reload.'
  624.             return 0
  625.  
  626.         
  627.         def help_read(self):
  628.             print >>self.stream, 'Read in profile data from a specified file.'
  629.  
  630.         
  631.         def do_reverse(self, line):
  632.             self.stats.reverse_order()
  633.             return 0
  634.  
  635.         
  636.         def help_reverse(self):
  637.             print >>self.stream, 'Reverse the sort order of the profiling report.'
  638.  
  639.         
  640.         def do_sort(self, line):
  641.             abbrevs = self.stats.get_sort_arg_defs()
  642.             if line and not filter((lambda x, a = abbrevs: x not in a), line.split()):
  643.                 self.stats.sort_stats(*line.split())
  644.             else:
  645.                 print >>self.stream, 'Valid sort keys (unique prefixes are accepted):'
  646.                 for key, value in Stats.sort_arg_dict_default.iteritems():
  647.                     print >>self.stream, '%s -- %s' % (key, value[1])
  648.                 
  649.             return 0
  650.  
  651.         
  652.         def help_sort(self):
  653.             print >>self.stream, 'Sort profile data according to specified keys.'
  654.             print >>self.stream, "(Typing `sort' without arguments lists valid keys.)"
  655.  
  656.         
  657.         def complete_sort(self, text, *args):
  658.             return _[1]
  659.  
  660.         
  661.         def do_stats(self, line):
  662.             return self.generic('print_stats', line)
  663.  
  664.         
  665.         def help_stats(self):
  666.             print >>self.stream, 'Print statistics from the current stat object.'
  667.             self.generic_help()
  668.  
  669.         
  670.         def do_strip(self, line):
  671.             self.stats.strip_dirs()
  672.             return 0
  673.  
  674.         
  675.         def help_strip(self):
  676.             print >>self.stream, 'Strip leading path information from filenames in the report.'
  677.  
  678.         
  679.         def postcmd(self, stop, line):
  680.             if stop:
  681.                 return stop
  682.  
  683.  
  684.     import sys
  685.     if len(sys.argv) > 1:
  686.         initprofile = sys.argv[1]
  687.     else:
  688.         initprofile = None
  689.     
  690.     try:
  691.         browser = ProfileBrowser(initprofile)
  692.         print >>browser.stream, 'Welcome to the profile statistics browser.'
  693.         browser.cmdloop()
  694.         print >>browser.stream, 'Goodbye.'
  695.     except KeyboardInterrupt:
  696.         pass
  697.  
  698.  
  699.