- re-implement list and adi commands using RequestSplitter - numerous small cleanups and clarity improvements - notably, adi now prints similar output to select when adding requests - lxml is needed to provide more fully-featured xpath implementation
114 lines
3.9 KiB
Python
114 lines
3.9 KiB
Python
from lxml import etree as ET
|
|
|
|
class RequestSplitter(object):
|
|
def __init__(self, api, requests, in_ring):
|
|
self.api = api
|
|
self.requests = requests
|
|
self.in_ring = in_ring
|
|
self.requests_ignored = self.api.get_ignored_requests()
|
|
self.reset()
|
|
|
|
def reset(self):
|
|
self.filters = []
|
|
self.groups = []
|
|
|
|
# after split()
|
|
self.filtered = []
|
|
self.other = []
|
|
self.grouped = {}
|
|
|
|
def filter_add(self, xpath):
|
|
self.filters.append(ET.XPath(xpath))
|
|
|
|
def filter_add_requests(self, requests):
|
|
requests = ' ' + ' '.join(requests) + ' '
|
|
self.filter_add('contains("{requests}", concat(" ", @id, " ")) or '
|
|
'contains("{requests}", concat(" ", ./action/target/@package, " "))'
|
|
.format(requests=requests))
|
|
|
|
def group_by(self, xpath):
|
|
self.groups.append(ET.XPath(xpath))
|
|
|
|
def filter_only(self):
|
|
ret = []
|
|
for request in self.requests:
|
|
target_package = request.find('./action/target').get('package')
|
|
self.suppliment(request, target_package)
|
|
if self.filter_check(request):
|
|
ret.append(request)
|
|
return ret
|
|
|
|
def split(self):
|
|
for request in self.requests:
|
|
target_package = request.find('./action/target').get('package')
|
|
self.suppliment(request, target_package)
|
|
|
|
if not self.filter_check(request):
|
|
continue
|
|
|
|
if self.in_ring != (not self.api.ring_packages.get(target_package)):
|
|
# Request is of desired ring type.
|
|
key = self.group_key_build(request)
|
|
if key not in self.grouped:
|
|
self.grouped[key] = {
|
|
'bootstrap_required': False,
|
|
'requests': [],
|
|
}
|
|
|
|
self.grouped[key]['requests'].append(request)
|
|
|
|
ring = request.find('./action/target').get('ring')
|
|
if ring and ring.startswith('0'):
|
|
self.grouped[key]['bootstrap_required'] = True
|
|
else:
|
|
self.other.append(request)
|
|
|
|
def suppliment(self, request, target_package):
|
|
""" Provide additional information for grouping """
|
|
devel = self.devel_project_get(request, target_package)
|
|
if devel:
|
|
request.find('./action/source').set('devel_project', devel)
|
|
|
|
ring = self.ring_get(target_package)
|
|
if ring:
|
|
request.find('./action/target').set('ring', ring)
|
|
|
|
request_id = int(request.get('id'))
|
|
if request_id in self.requests_ignored:
|
|
request.set('ignored', self.requests_ignored[request_id])
|
|
else:
|
|
request.set('ignored', 'false')
|
|
|
|
def ring_get(self, target_package):
|
|
if self.api.crings:
|
|
ring = self.api.ring_packages_for_links.get(target_package)
|
|
if ring:
|
|
# Cut off *:Rings: prefix.
|
|
return ring[len(self.api.crings)+1:]
|
|
return None
|
|
|
|
def devel_project_get(self, request, target_project):
|
|
# Preserve logic from adi and note that not Leap development friendly.
|
|
source = request.find('./action/source')
|
|
devel = self.api.get_devel_project(source.get('project'), source.get('package'))
|
|
if devel is None and self.api.project.startswith('openSUSE:'):
|
|
devel = self.api.get_devel_project('openSUSE:Factory', target_project)
|
|
return devel
|
|
|
|
def filter_check(self, request):
|
|
for xpath in self.filters:
|
|
if not xpath(request):
|
|
return False
|
|
return True
|
|
|
|
def group_key_build(self, request):
|
|
if len(self.groups) == 0:
|
|
return 'all'
|
|
|
|
key = []
|
|
for xpath in self.groups:
|
|
element = xpath(request)
|
|
if element:
|
|
key.append(element[0])
|
|
return '__'.join(key)
|