File niceresults.py of Package osc-plugin-niceresults
# -*- coding: utf-8 -*-
# Coloured results plugin for osc
# Author: Pascal Bleser <pascal.bleser@opensuse.org>
@cmdln.alias('nr')
def do_niceresults(self, subcmd, opts, *args):
"""${cmd_name}: show build results with a nice coloured output
${cmd_usage}
"""
import re
import conf
columns = [ 'prj', 'pac', 'rep', 'arch', 'u', 'status' ]
header = { 'prj': 'Project', 'pac': 'Package', 'rep': 'Repository', 'arch': 'Arch', 'status': 'Status', 'u': 'U', }
statusColumnIndex = columns.index('status')
symbol = {
'succeeded': u'\033[32;1m✔\033[0m',
'failed': u'\033[31m✘\033[0m',
'blocked': u'\033[34;1m▒\033[0m',
'disabled': u'\033[37m⬕\033[0m',
'scheduled': u'\033[35m♻\033[0m',
'outdated': '\033[31;1m*\033[0m',
'uptodate': u'\033[36;1m✔\033[0m',
}
color = {
'succeeded': '32',
'building': '33',
'failed': '31',
'expansion error': '31',
'blocked': '34',
'disabled': '30;1',
'scheduled': '35',
'outdated': '36;1',
}
fallbackColor = '0'
args = parseargs(args)
pacs = findpacs(args)
singlePac = len(pacs) <= 1
if singlePac:
columns = columns[2:]
nh = {}
for x, y in header.items():
if x in columns:
nh[x] = y
header = nh
statusColumnIndex = columns.index('status')
rows = []
rowlen = [len(header[x]) for x in columns]
cleanlen = [len(header[x]) for x in columns]
for pac in pacs:
f = show_results_meta(pac.apiurl, pac.prjname, pac.name)
tree = ET.parse(StringIO(''.join(f)))
root = tree.getroot()
for node in root.findall('result'):
rmap = {}
rmap['prj'] = pac.prjname
rmap['pac'] = pac.name
rmap['rep'] = node.get('repository')
rmap['arch'] = node.get('arch')
if 'dirty' in node.keys() and node.get('dirty'):
rmap['u'] = symbol['outdated']
else:
rmap['u'] = symbol['uptodate']
statusnode = node.find('status')
try:
rmap['status'] = statusnode.get('code')
except:
# code can be missing when package is too new:
rmap['status'] = "?"
if rmap['status'] in ['expansion error', 'broken', 'blocked']:
rmap['details'] = statusnode.find('details').text
if rmap['status'] == 'failed':
rmap['details'] = conf.config['apiurl'] + ('/result/%(prj)s/%(rep)s/%(pac)s/%(arch)s/log' % rmap)
row = []
i = 0
for col in columns:
rowlen[i] = max(rowlen[i], len(rmap[col]))
clean = re.subn(r"\033\[.+?m", '', rmap[col])[0]
cleanlen[i] = max(cleanlen[i], len(clean))
row.append(rmap[col])
i += 1
if 'details' in rmap:
row.append(rmap['details'])
rows.append(row)
cleanfmt = " │ ".join(map(lambda x: "%%-%d.%ds" % (x, x), cleanlen[:-1]) + \
["\033[%%sm%%-%d.%ds\033[0m" % (cleanlen[-1], cleanlen[-1])])
format = " │ ".join(map(lambda x: "%%-%d.%ds" % (x, x), rowlen[:-1]) + \
["\033[%%sm%%-%d.%ds\033[0m" % (rowlen[-1], rowlen[-1])])
print " ",
print cleanfmt % tuple([header[x] for x in columns[:-1]] + ["0", header[columns[-1]]])
print "──" + ("─┼─".join([x * '─' for x in cleanlen]))
for line in rows:
if line[statusColumnIndex] in color:
c = color[line[statusColumnIndex]]
else:
c = fallbackColor
if line[statusColumnIndex] in symbol:
s = symbol[line[statusColumnIndex]]
else:
s = ' '
print s,
print format % tuple(line[:(len(columns)-1)] + [c, line[statusColumnIndex]])
if len(line) > len(columns):
print " \033[31;1m└─▶ %s\033[0m" % line[-1]