| 1 |
import os, re, sys |
|---|
| 2 |
from xml.dom.minidom import parseString as dom |
|---|
| 3 |
from optparse import OptionParser, OptionValueError |
|---|
| 4 |
from math import ceil |
|---|
| 5 |
|
|---|
| 6 |
VERSION = '0.2' |
|---|
| 7 |
USAGE = "%prog [options] [filename-filter [...]]" |
|---|
| 8 |
DEFAULT_SORTKEYS = ['avgtime', 'totaltime', 'callcount'] |
|---|
| 9 |
class Item: |
|---|
| 10 |
which = ('avgtime', 'mintime', 'maxtime', 'totaltime', 'summary', 'callcount', 'filename', 'startline', 'endline') |
|---|
| 11 |
def __init__(self, elem): |
|---|
| 12 |
self.attrs = dict() |
|---|
| 13 |
for i in range(0, elem.attributes.length): |
|---|
| 14 |
x = elem.attributes.item(i) |
|---|
| 15 |
if not x.localName in self.which: |
|---|
| 16 |
continue |
|---|
| 17 |
val = x.nodeValue |
|---|
| 18 |
try: |
|---|
| 19 |
val = float(val) |
|---|
| 20 |
except: |
|---|
| 21 |
pass |
|---|
| 22 |
self.attrs[x.localName] = val |
|---|
| 23 |
self.attrs['avgtime'] = ceil(self['totaltime'] * 1000 / self['callcount']) / 1000.0 |
|---|
| 24 |
def __repr__(self): |
|---|
| 25 |
return self['filename'] + ": " + self['summary'] |
|---|
| 26 |
def __getitem__(self, x): |
|---|
| 27 |
return self.attrs[x] |
|---|
| 28 |
|
|---|
| 29 |
def printTable(inlist, sortkey, fns): |
|---|
| 30 |
s = inlist[:] |
|---|
| 31 |
if len(fns): |
|---|
| 32 |
s = filter(lambda x: x['filename'] in fns, inlist) |
|---|
| 33 |
s.sort(lambda x,y: cmp(y[sortkey], x[sortkey])) |
|---|
| 34 |
print "<h1>Sorted by: %s</h1>" % sortkey |
|---|
| 35 |
print '<table border="1">' |
|---|
| 36 |
for i in s: |
|---|
| 37 |
print '<tr><th colspan="2">%s</th></tr>' % i['filename'] |
|---|
| 38 |
print '<tr><td>%s</td><td>%s</td></tr>' % (str(i[sortkey]), i['summary']) |
|---|
| 39 |
print '</table>' |
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
def callback_opts_keys(option, opt, value, parser): |
|---|
| 43 |
if value not in Item.which: |
|---|
| 44 |
raise OptionValueError("sortkey must be one of the following:\n%s" % ', '.join(Item.which)) |
|---|
| 45 |
parser.skeys += value, |
|---|
| 46 |
|
|---|
| 47 |
def main(): |
|---|
| 48 |
print >> sys.stderr, """Venkman Profiler XML parser/sorter |
|---|
| 49 |
(C) 2007 Nils Maier - MPL-Tri license |
|---|
| 50 |
""" |
|---|
| 51 |
parser = OptionParser(version=VERSION, usage=USAGE) |
|---|
| 52 |
parser.add_option( |
|---|
| 53 |
'-f', |
|---|
| 54 |
'--file', |
|---|
| 55 |
type="string", |
|---|
| 56 |
help="file to parse (default: stdin)", |
|---|
| 57 |
metavar="FILE" |
|---|
| 58 |
) |
|---|
| 59 |
parser.add_option( |
|---|
| 60 |
'-s', |
|---|
| 61 |
'--sortkey', |
|---|
| 62 |
metavar='KEY', |
|---|
| 63 |
action="callback", |
|---|
| 64 |
type="string", |
|---|
| 65 |
help="which keys to use for sorting (default: %s)" % ', '.join(DEFAULT_SORTKEYS), |
|---|
| 66 |
callback=callback_opts_keys |
|---|
| 67 |
) |
|---|
| 68 |
parser.skeys = [] |
|---|
| 69 |
opts, args = parser.parse_args(sys.argv) |
|---|
| 70 |
args = args[1:] |
|---|
| 71 |
|
|---|
| 72 |
if not opts.file: |
|---|
| 73 |
opts.file = sys.stdin |
|---|
| 74 |
else: |
|---|
| 75 |
opts.file = open(opts.file, "r") |
|---|
| 76 |
if not len(parser.skeys): |
|---|
| 77 |
parser.skeys = DEFAULT_SORTKEYS |
|---|
| 78 |
|
|---|
| 79 |
doc = dom(opts.file.read()) |
|---|
| 80 |
|
|---|
| 81 |
l = [] |
|---|
| 82 |
for e in doc.getElementsByTagName('item'): |
|---|
| 83 |
l += Item(e), |
|---|
| 84 |
|
|---|
| 85 |
for k in parser.skeys: |
|---|
| 86 |
printTable(l, k, args) |
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
if __name__ == '__main__': |
|---|
| 90 |
main() |
|---|