1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-12-24 17:16:12 +01:00

- refactored package result code a bit (fixes #180)

Note: this commit "breaks" the existing get_package_results api, because
it returns a generator, which yields a result xml, instead of a list of
result dicts.
This commit is contained in:
Marcus Huewe 2016-02-07 00:55:23 +01:00
parent ffb37960ff
commit f3a1d12a96
2 changed files with 76 additions and 53 deletions

View File

@ -4970,18 +4970,23 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.xml and opts.csv: if opts.xml and opts.csv:
raise oscerr.WrongOptions("--xml and --csv are mutual exclusive") raise oscerr.WrongOptions("--xml and --csv are mutual exclusive")
args = [ apiurl, project, package, opts.last_build, opts.repo, opts.arch ] kwargs = {'apiurl': apiurl, 'project': project, 'package': package,
if opts.xml: 'lastbuild': opts.last_build, 'repository': opts.repo,
print(''.join(show_results_meta(*args)), end=' ') 'arch': opts.arch, 'wait': opts.watch}
elif opts.csv: if opts.xml or opts.csv:
# ignore _oldstate key for xml in get_package_results(**kwargs):
results = [r for r in get_package_results(*args) if not '_oldstate' in r] if opts.xml:
print('\n'.join(format_results(results, opts.format))) print(xml, end='')
else:
# csv formatting
results = result_xml_to_dicts(xml)
print('\n'.join(format_results(results, opts.format)))
else: else:
args.append(opts.verbose) kwargs['verbose'] = opts.verbose
args.append(opts.watch) kwargs['wait'] = opts.watch
args.append("\n") kwargs['printJoin'] = '\n'
get_results(*args) get_results(**kwargs)
# WARNING: this function is also called by do_results. You need to set a default there # WARNING: this function is also called by do_results. You need to set a default there
# as well when adding a new option! # as well when adding a new option!

View File

@ -5381,64 +5381,53 @@ def show_prj_results_meta(apiurl, prj):
return f.readlines() return f.readlines()
def get_package_results(apiurl, prj, package, lastbuild=None, repository=[], arch=[], oldstate=None): def result_xml_to_dicts(xml):
""" return a package results as a list of dicts """ # assumption: xml contains at most one status element (maybe we should
# generalize this to arbitrary status element)
root = ET.fromstring(xml)
r = [] r = []
f = show_results_meta(apiurl, prj, package, lastbuild, repository, arch, oldstate)
root = ET.fromstring(''.join(f))
r.append( {'_oldstate': root.get('state')} )
for node in root.findall('result'): for node in root.findall('result'):
rmap = {} rmap = {}
rmap['project'] = rmap['prj'] = prj rmap['project'] = rmap['prj'] = node.get('project')
rmap['pkg'] = rmap['package'] = rmap['pac'] = package
rmap['repository'] = rmap['repo'] = rmap['rep'] = node.get('repository') rmap['repository'] = rmap['repo'] = rmap['rep'] = node.get('repository')
rmap['arch'] = node.get('arch') rmap['arch'] = node.get('arch')
rmap['state'] = node.get('state') rmap['state'] = node.get('state')
rmap['dirty'] = node.get('dirty') rmap['dirty'] = node.get('dirty')
rmap['repostate'] = node.get('code') rmap['repostate'] = node.get('code')
rmap['pkg'] = rmap['package'] = rmap['pac'] = ''
rmap['code'] = ''
rmap['details'] = '' rmap['details'] = ''
details = None details = None
statusnode = node.find('status') statusnode = node.find('status')
if statusnode != None: if statusnode is not None:
# the way currently use this function, there should be
# always a status element
rmap['pkg'] = rmap['package'] = rmap['pac'] = statusnode.get('package')
rmap['code'] = statusnode.get('code', '') rmap['code'] = statusnode.get('code', '')
details = statusnode.find('details') details = statusnode.find('details')
else: if details is not None:
rmap['code'] = ''
if details != None:
rmap['details'] = details.text rmap['details'] = details.text
rmap['dirty'] = rmap['dirty'] == 'true' rmap['dirty'] = rmap['dirty'] == 'true'
r.append(rmap) r.append(rmap)
return r return r
def format_results(results, format): def format_results(results, format):
"""apply selected format on each dict in results and return it as a list of strings""" """apply selected format on each dict in results and return it as a list of strings"""
return [format % r for r in results] return [format % r for r in results]
def get_results(apiurl, prj, package, lastbuild=None, repository=[], arch=[], verbose=False, wait=False, printJoin=None):
r = [] def get_results(apiurl, project, package, verbose=False, printJoin='', *args, **kwargs):
"""returns list of/or prints a human readable status for the specified package"""
# hmm the function name is a bit too generic - something like
# get_package_results_human would be better, but this would break the existing
# api (unless we keep get_results around as well)...
result_line_templ = '%(rep)-20s %(arch)-10s %(status)s' result_line_templ = '%(rep)-20s %(arch)-10s %(status)s'
oldstate = None r = []
for results in get_package_results(apiurl, project, package, **kwargs):
while True: r = []
waiting = False for res in result_xml_to_dicts(results):
results = r = []
try:
results = get_package_results(apiurl, prj, package, lastbuild, repository, arch, oldstate)
except HTTPError as e:
# check for simple timeout error and fetch again
if e.code == 502 or e.code == 504:
# re-try result request
continue
raise
for res in results:
if '_oldstate' in res: if '_oldstate' in res:
oldstate = res['_oldstate'] oldstate = res['_oldstate']
continue continue
@ -5450,30 +5439,59 @@ def get_results(apiurl, prj, package, lastbuild=None, repository=[], arch=[], ve
else: else:
res['status'] += ': %s' % (res['details'], ) res['status'] += ': %s' % (res['details'], )
if res['dirty']: if res['dirty']:
waiting = True
if verbose: if verbose:
res['status'] = 'outdated (was: %s)' % res['status'] res['status'] = 'outdated (was: %s)' % res['status']
else: else:
res['status'] += '*' res['status'] += '*'
elif res['code'] in ('succeeded') and res['repostate'] != "published": elif res['code'] in ('succeeded') and res['repostate'] != "published":
waiting = True
if verbose: if verbose:
res['status'] += '(unpublished)' res['status'] += '(unpublished)'
else: else:
res['status'] += '*' res['status'] += '*'
if res['code'] in ('blocked', 'scheduled', 'dispatching', 'building', 'signing', 'finished'):
waiting = True
r.append(result_line_templ % res) r.append(result_line_templ % res)
if printJoin: if printJoin:
print(printJoin.join(r)) print(printJoin.join(r))
if wait == False or waiting == False:
break
return r return r
def get_package_results(apiurl, project, package, wait=False, *args, **kwargs):
"""generator that returns a the package results as an xml structure"""
xml = ''
waiting_states = ('blocked', 'scheduled', 'dispatching', 'building',
'signing', 'finished')
while True:
waiting = False
try:
xml = ''.join(show_results_meta(apiurl, project, package, *args, **kwargs))
except HTTPError as e:
# check for simple timeout error and fetch again
if e.code == 502 or e.code == 504:
# re-try result request
continue
raise
root = ET.fromstring(xml)
kwargs['oldstate'] = root.get('state')
for result in root.findall('result'):
if result.get('dirty') is not None:
waiting = True
break
elif result.get('code') in waiting_states:
waiting = True
break
elif (result.get('code') == 'succeeded'
and result.get('repostate') != 'published'):
waiting = True
break
if not wait or not waiting:
break
else:
yield xml
yield xml
def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=None, name_filter=None, arch=None, repo=None, vertical=None, show_excluded=None): def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=None, name_filter=None, arch=None, repo=None, vertical=None, show_excluded=None):
#print '----------------------------------------' #print '----------------------------------------'
global buildstatus_symbols global buildstatus_symbols