12:10e706a1f650
Anton Shestakov <engored@ya.ru>, Tue, 05 May 2015 23:53:29 +0800
viewer: second time in .tsv view

next change 13:dce6d8966d49
previous change 11:255526e91799

viewer.py

Permissions: -rwxr-xr-x

Other formats: Feeds:
#!/usr/bin/env python
import colorsys
import json
import logging
import re
import sqlite3
import subprocess
from tornado.ioloop import IOLoop
from tornado.options import define, options
from tornado.web import Application, RequestHandler, URLSpec
from settings import DBPATH, HG, TEMPLATES, TESTHGREPO
from bench import MARKS
define('listen', metavar='IP', default='127.0.0.1')
define('port', metavar='PORT', default=8065, type=int)
define('xheaders', metavar='True|False', default=False, type=bool)
define('debug', metavar='True|False', default=False, type=bool)
def getinfo(revset):
output = subprocess.check_output([HG, 'log', '-R', TESTHGREPO, '-T', 'json', '-r', revset])
return json.loads(output)
class BaseHandler(RequestHandler):
def prepare(self):
self.conn = sqlite3.connect(DBPATH)
super(BaseHandler, self).prepare()
def on_finish(self):
self.conn.close()
class IndexHandler(BaseHandler):
def get(self):
self.redirect('results.html')
class ResultsHandler(BaseHandler):
def get(self, ext):
if ext == 'tsv':
self.results_tsv()
elif ext == 'asc':
self.results_asc()
elif ext == 'html':
self.results_html()
def getchangesets(self):
rev = self.get_argument('rev', 'tip')
revcount = 120
return getinfo('first({}:0, {})'.format(rev, revcount))
def getresults(self, changesets):
results = {}
limits = {
mark:
self.conn.execute(
'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?',
(mark, False)).fetchone()
+
self.conn.execute(
'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?',
(mark, True)).fetchone()
for mark in MARKS
}
for cset in changesets:
node = cset['node']
resultsq = self.conn.execute(
'SELECT mark, time, cache FROM results WHERE node = ?',
(node,))
for mark, time, cache in resultsq:
results.setdefault(node, {}).setdefault(mark, [None, None, None, None])
if not cache:
color = green_to_red(limits[mark][0:2], time) if time is not None else None
results[node][mark][0:2] = [time, color]
else:
color = green_to_red(limits[mark][2:4], time) if time is not None else None
results[node][mark][2:4] = [time, color]
return results
def results_tsv(self):
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
changesets = self.getchangesets()
results = self.getresults(changesets)
self.write('rev\tnode')
for mark in MARKS:
self.write('\t{0} (without cache)\t{0} (with cache)'.format(mark))
self.write('\n')
for cset in changesets:
self.write('{rev}\t{node}'.format(**cset))
for mark in MARKS:
marks = results.get(cset['node'], {}).get(mark, ('', '', ''))
self.write('\t{0}\t{2}'.format(*marks))
self.write('\n')
self.finish()
def results_asc(self):
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
rev = self.get_argument('rev', 'tip')
revcount = 120
regex = re.compile(r'^[-\\|/+ ]+([0-9a-f]{40})$')
template = '{rev}:{node|short} {tags} {date|isodate} {author|user} {desc|firstline|strip}\n {node}\n\n'
revset = 'first({}:0, {})'.format(rev, revcount)
cmd = [HG, 'log', '-R', TESTHGREPO, '-G', '-T', template, '-r', revset]
graph = subprocess.Popen(cmd, stdout=subprocess.PIPE)
while graph.poll() is None:
line = graph.stdout.readline()
matches = regex.findall(line)
for match in matches:
msg = []
rows = self.conn.execute(
'SELECT mark, time FROM results WHERE node = ? AND cache = ?',
(match, False))
for row in rows:
msg.append('{}: {:.2g}s'.format(*row))
line = line.replace(match, ' '.join(msg))
self.write(line)
self.finish()
def results_html(self):
changesets = self.getchangesets()
results = self.getresults(changesets)
self.render('results.html', changesets=changesets, marks=MARKS, results=results)
def green_to_red((low, high), value):
hue = (value - low) / (high - low) if high != low else 0.5
r, g, b = colorsys.hsv_to_rgb((1 - hue) * 0.3, 1, 1)
return (int(r * 255), int(g * 255), int(b * 255))
class Viewer(Application):
def __init__(self):
handlers = [
URLSpec(r'/', IndexHandler),
URLSpec(r'/results\.(html|tsv|asc)', ResultsHandler),
]
settings = dict(
template_path=TEMPLATES,
debug=options.debug
)
super(Viewer, self).__init__(handlers, **settings)
def listen(self, port, address='', **kwargs):
logging.info('{} is serving on {}:{}'.format(self.__class__.__name__, address, port))
super(Viewer, self).listen(port, address, **kwargs)
def main():
options.parse_command_line()
application = Viewer()
application.listen(options.port, address=options.listen, xheaders=options.xheaders)
IOLoop.instance().start()
if __name__ == '__main__':
main()