82:96d4858f3d3f
Anton Shestakov <av6@dwimlabs.net>, Sat, 02 Jul 2016 13:10:27 +0800
incoming: un-anchor "job failed" regex Allows catching lines from bad_exit() (ed7f35f).

next change 99:b0bcc3b9dc46
previous change 78:06a1f6536049

viewer.py

Permissions: -rwxr-xr-x

Other formats: Feeds:
#!/usr/bin/env python
from __future__ import absolute_import, division
import logging
import os
import traceback
from peewee import DoesNotExist
from tornado.escape import json_decode
from tornado.ioloop import IOLoop
from tornado.options import define, options
from tornado.web import Application, HTTPError, RequestHandler, URLSpec
from tornado.web import ErrorHandler as BaseErrorHandler
from candolint import uimodules
from candolint.models import database, Project, Change, Check
rel = lambda *x: os.path.abspath(os.path.join(os.path.dirname(__file__), *x))
define('listen', metavar='IP', default='127.0.0.1')
define('port', metavar='PORT', default=8033, type=int)
define('xheaders', metavar='True|False', default=False, type=bool)
define('debug', metavar='True|False', default=False, type=bool)
def get_or_404(query, *args, **kwargs):
try:
return query.get(*args, **kwargs)
except DoesNotExist:
raise HTTPError(404)
def get_project_or_404(domain, user, name):
pq = Project.select().where(
Project.domain == domain,
Project.user == (user if user != '-' else None),
Project.name == name)
return get_or_404(pq)
class BaseHandler(RequestHandler):
def prepare(self):
database.connect()
super(BaseHandler, self).prepare()
def on_finish(self):
if not database.is_closed():
database.close()
def write_error(self, status_code, **kwargs):
data = {
'code': status_code,
'message': self._reason,
'debug_message': ''
}
if 'exc_info' in kwargs:
if self.settings.get('serve_traceback'):
fexc = traceback.format_exception(*kwargs['exc_info'])
data['debug_message'] = '\n'.join(fexc)
if status_code == 404:
self.render('404.html', **data)
else:
self.render('500.html', **data)
class IndexHandler(BaseHandler):
def get(self):
checks = (Check
.select(Check, Project, Change)
.join(Project)
.switch(Check)
.join(Change)
.group_by(Check.project))
self.render('index.html', checks=checks)
class ProjectHandler(BaseHandler):
def get(self, domain, user, name):
project = get_project_or_404(domain, user, name)
checks = (Check
.select(Check, Change)
.join(Change)
.where(Check.project == project)
.limit(10))
self.render('project.html', project=project, checks=checks)
class CheckHandler(BaseHandler):
def get(self, domain, user, name, check_num):
project = get_project_or_404(domain, user, name)
if check_num == 'latest':
check = get_or_404(Check, project=project)
else:
check = get_or_404(Check, project=project, ordinal=check_num)
lines = json_decode(check.lines)
self.render('check.html', project=project, check=check, lines=lines)
class StatusHandler(BaseHandler):
def get(self, domain, user, name):
project = get_project_or_404(domain, user, name)
check = get_or_404(Check, project=project)
parts = [('#555', 30, 14.5, 'lint')]
if not check.success:
parts.append(('#777', 62, 30.5, 'unknown'))
elif check.errors or check.warnings:
if check.errors:
msg = self.locale.translate('{} error', '{} errors', check.errors)
text = msg.format(check.errors)
width = 7 + 6 * len(text) + 7
parts.append(('#da314b', width, width // 2 - 0.5, text))
if check.warnings:
msg = self.locale.translate('{} warning', '{} warnings', check.warnings)
text = msg.format(check.warnings)
width = 7 + 6 * len(text) + 9
parts.append(('#faa732', width, width // 2 + 0.5, text))
else:
parts.append(('#8cc14c', 40, 19.5, 'none'))
width = sum(p[1] for p in parts)
self.set_header('Content-Type', 'image/svg+xml; charset=utf-8')
self.render('status.svg', width=width, parts=parts, height=20)
class ErrorHandler(BaseHandler, BaseErrorHandler):
pass
class CandolintViewer(Application):
def __init__(self):
handlers = [
URLSpec(r'/', IndexHandler),
URLSpec(r'/([.a-z0-9_-]+)/([^/]+)/([^/]+)', ProjectHandler),
URLSpec(r'/([.a-z0-9_-]+)/([^/]+)/([^/]+)/([\d]+|latest)', CheckHandler),
URLSpec(r'/([.a-z0-9_-]+)/([^/]+)/([^/]+)/status\.svg', StatusHandler),
URLSpec(r'.*', ErrorHandler, {'status_code': 404})
]
settings = dict(
static_path=rel('static'),
template_path=rel('templates'),
ui_modules=uimodules,
debug=options.debug
)
super(CandolintViewer, self).__init__(handlers, **settings)
if options.debug:
logging.getLogger('peewee').setLevel(logging.DEBUG)
database.init(rel('database.sqlite'))
def listen(self, port, address='', **kwargs):
name = self.__class__.__name__
logging.info('%s is serving on %s:%d', name, address, port)
super(CandolintViewer, self).listen(port, address, **kwargs)
def main():
options.parse_command_line()
application = CandolintViewer()
application.listen(options.port, address=options.listen, xheaders=options.xheaders)
IOLoop.instance().start()
if __name__ == '__main__':
main()