Revamp "qvm-template search" and finish TODOs.

This commit is contained in:
WillyPillow 2020-07-26 02:11:57 +08:00
parent 37a72ecebf
commit 5e76bdb5f1

View File

@ -479,54 +479,60 @@ def search(args, app):
WEIGHT_NAME = 1 << 2 WEIGHT_NAME = 1 << 2
WEIGHT_SUMMARY = 1 << 1 WEIGHT_SUMMARY = 1 << 1
search_res = collections.defaultdict(int) search_res = collections.defaultdict(list)
first = True
for keyword in args.templates: for keyword in args.templates:
local_res = collections.defaultdict(int)
#pylint: disable=unused-variable #pylint: disable=unused-variable
for idx, (name, epoch, version, release, reponame, dlsize, summary) \ for idx, (name, epoch, version, release, reponame, dlsize, summary) \
in enumerate(query_res): in enumerate(query_res):
if fnmatch.fnmatch(name, '*' + keyword + '*'): if fnmatch.fnmatch(name, '*' + keyword + '*'):
local_res[idx] += WEIGHT_NAME exact = keyword == name
weight = WEIGHT_NAME_EXACT if exact else WEIGHT_NAME
search_res[idx].append((weight, keyword, exact))
if fnmatch.fnmatch(summary, '*' + keyword + '*'): if fnmatch.fnmatch(summary, '*' + keyword + '*'):
local_res[idx] += WEIGHT_SUMMARY search_res[idx].append(
if keyword == name: (WEIGHT_SUMMARY, keyword, keyword == summary))
local_res[idx] += WEIGHT_NAME_EXACT
for key, val in local_res.items(): # TODO: Search in description and URL for --all?
if args.all or first or key in search_res: # Requires changes to the qrexec call qubes.TemplateSearch
search_res[key] += val if not args.all:
first = False keywords = set(args.templates)
idxs = list(search_res.keys())
for idx in idxs:
if keywords != set(x[1] for x in search_res[idx]):
del search_res[idx]
def key_func(x): def key_func(x):
# Order by weight DESC, name ASC # ORDER BY weight DESC, list_of_needles ASC, name ASC
weight = x[1] idx, needles = x
name = query_res[x[0]][0] weight = sum(t[0] for t in needles)
return (-weight, name) name = query_res[idx][0]
return (-weight, needles, name)
search_res = sorted(search_res.items(), key=key_func) search_res = sorted(search_res.items(), key=key_func)
def gen_header(idx, weight): def gen_header(idx, needles):
# FIXME: "Exactly Matched" is printed even if the summary is not
# exactly matching
# TODO: Print matching keywords
#pylint: disable=unused-variable #pylint: disable=unused-variable
name, epoch, version, release, reponame, dlsize, summary = \ name, epoch, version, release, reponame, dlsize, summary = \
query_res[idx] query_res[idx]
keys = [] fields = []
if weight & WEIGHT_NAME: weight_types = set(x[0] for x in needles)
keys.append('Name') if WEIGHT_NAME in weight_types:
if weight & WEIGHT_SUMMARY: fields.append('Name')
keys.append('Summary') if WEIGHT_SUMMARY in weight_types:
match = 'Exactly Matched' if weight & WEIGHT_NAME_EXACT else 'Matched' fields.append('Summary')
return ' & '.join(keys) + ' ' + match exact = all(x[-1] for x in needles)
match = 'Exactly Matched' if exact else 'Matched'
keywords = sorted(list(set(x[1] for x in needles)))
return ' & '.join(fields) + ' ' + match + ': ' + ', '.join(keywords)
last_weight = -1 last_header = ''
for idx, weight in search_res: for idx, needles in search_res:
if last_weight != weight: # Print headers
last_weight = weight cur_header = gen_header(idx, needles)
# Print headers if last_header != cur_header:
last_header = cur_header
# XXX: The style is different from that of DNF # XXX: The style is different from that of DNF
print(gen_header(idx, weight)) print('===', cur_header, '===')
name, epoch, version, release, reponame, dlsize, summary = \ name, epoch, version, release, reponame, dlsize, summary = \
query_res[idx] query_res[idx]
print(name, ':', summary) print(name, ':', summary)