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]

openSUSE Build Service is sponsored by