openSUSE-release-tools/osclib/request_splitter.py
Jimmy Berry 69f662685c Add RequestSplitter for common filtering and grouping or requests.
- 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
2017-01-24 22:21:10 -06:00

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)