diff options
author | Michal Čihař <nijel@debian.org> | 2019-02-17 09:12:42 +0100 |
---|---|---|
committer | Michal Čihař <nijel@debian.org> | 2019-02-17 09:12:42 +0100 |
commit | d0395582092c53d328a3071878a9327894ef1284 (patch) | |
tree | 3b3c955a2dbbb59ab22071e3ecaa6722fb45f252 /osc/util/debquery.py | |
parent | 3443a428fefbd5715c8cd5f7c967e9d0db51446f (diff) |
New upstream version 0.164.2
Diffstat (limited to 'osc/util/debquery.py')
-rw-r--r-- | osc/util/debquery.py | 131 |
1 files changed, 78 insertions, 53 deletions
diff --git a/osc/util/debquery.py b/osc/util/debquery.py index 4c2e0e5..3d56880 100644 --- a/osc/util/debquery.py +++ b/osc/util/debquery.py @@ -5,8 +5,10 @@ from . import ar import os.path import re import tarfile -import StringIO +from io import BytesIO from . import packagequery +import itertools + HAVE_LZMA = True try: @@ -14,13 +16,21 @@ try: except ImportError: HAVE_LZMA = False + +if (not hasattr(itertools, 'zip_longest') + and hasattr(itertools, 'izip_longest')): + # python2 case + itertools.zip_longest = itertools.izip_longest + + class DebError(packagequery.PackageError): pass class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): - default_tags = ('package', 'version', 'release', 'epoch', 'architecture', 'description', - 'provides', 'depends', 'pre_depends', 'conflicts', 'breaks') + default_tags = (b'package', b'version', b'release', b'epoch', + b'architecture', b'description', b'provides', b'depends', + b'pre_depends', b'conflicts', b'breaks') def __init__(self, fh): self.__file = fh @@ -31,24 +41,24 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): def read(self, all_tags=False, self_provides=True, *extra_tags): arfile = ar.Ar(fh = self.__file) arfile.read() - debbin = arfile.get_file('debian-binary') + debbin = arfile.get_file(b'debian-binary') if debbin is None: raise DebError(self.__path, 'no debian binary') - if debbin.read() != '2.0\n': + if debbin.read() != b'2.0\n': raise DebError(self.__path, 'invalid debian binary format') - control = arfile.get_file('control.tar.gz') + control = arfile.get_file(b'control.tar.gz') if control is not None: # XXX: python2.4 relies on a name tar = tarfile.open(name='control.tar.gz', fileobj=control) else: - control = arfile.get_file('control.tar.xz') + control = arfile.get_file(b'control.tar.xz') if control is None: raise DebError(self.__path, 'missing control.tar') if not HAVE_LZMA: raise DebError(self.__path, 'can\'t open control.tar.xz without python-lzma') decompressed = lzma.decompress(control.read()) tar = tarfile.open(name="control.tar.xz", - fileobj=StringIO.StringIO(decompressed)) + fileobj=BytesIO(decompressed)) try: name = './control' # workaround for python2.4's tarfile module @@ -64,94 +74,98 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): def __parse_control(self, control, all_tags=False, self_provides=True, *extra_tags): data = control.readline().strip() while data: - field, val = re.split(':\s*', data.strip(), 1) + field, val = re.split(b':\s*', data.strip(), 1) data = control.readline() - while data and re.match('\s+', data): - val += '\n' + data.strip() + while data and re.match(b'\s+', data): + val += b'\n' + data.strip() data = control.readline().rstrip() - field = field.replace('-', '_').lower() + field = field.replace(b'-', b'_').lower() if field in self.default_tags + extra_tags or all_tags: # a hyphen is not allowed in dict keys self.fields[field] = val - versrel = self.fields['version'].rsplit('-', 1) + versrel = self.fields[b'version'].rsplit(b'-', 1) if len(versrel) == 2: - self.fields['version'] = versrel[0] - self.fields['release'] = versrel[1] + self.fields[b'version'] = versrel[0] + self.fields[b'release'] = versrel[1] else: - self.fields['release'] = None - verep = self.fields['version'].split(':', 1) + self.fields[b'release'] = None + verep = self.fields[b'version'].split(b':', 1) if len(verep) == 2: - self.fields['epoch'] = verep[0] - self.fields['version'] = verep[1] + self.fields[b'epoch'] = verep[0] + self.fields[b'version'] = verep[1] else: - self.fields['epoch'] = '0' - self.fields['provides'] = [ i.strip() for i in re.split(',\s*', self.fields.get('provides', '')) if i ] - self.fields['depends'] = [ i.strip() for i in re.split(',\s*', self.fields.get('depends', '')) if i ] - self.fields['pre_depends'] = [ i.strip() for i in re.split(',\s*', self.fields.get('pre_depends', '')) if i ] - self.fields['conflicts'] = [ i.strip() for i in re.split(',\s*', self.fields.get('conflicts', '')) if i ] - self.fields['breaks'] = [ i.strip() for i in re.split(',\s*', self.fields.get('breaks', '')) if i ] - self.fields['recommends'] = [ i.strip() for i in re.split(',\s*', self.fields.get('recommends', '')) if i ] - self.fields['suggests'] = [ i.strip() for i in re.split(',\s*', self.fields.get('suggests', '')) if i ] - self.fields['enhances'] = [ i.strip() for i in re.split(',\s*', self.fields.get('enhances', '')) if i ] + self.fields[b'epoch'] = b'0' + self.fields[b'provides'] = self._split_field_value(b'provides') + self.fields[b'depends'] = self._split_field_value(b'depends') + self.fields[b'pre_depends'] = self._split_field_value(b'pre_depends') + self.fields[b'conflicts'] = self._split_field_value(b'conflicts') + self.fields[b'breaks'] = self._split_field_value(b'breaks') + self.fields[b'recommends'] = self._split_field_value(b'recommends') + self.fields[b'suggests'] = self._split_field_value(b'suggests') + self.fields[b'enhances'] = self._split_field_value(b'enhances') if self_provides: # add self provides entry - self.fields['provides'].append('%s (= %s)' % (self.name(), '-'.join(versrel))) + self.fields[b'provides'].append(b'%s (= %s)' % (self.name(), b'-'.join(versrel))) + + def _split_field_value(self, field, delimeter=b',\s*'): + return [i.strip() + for i in re.split(delimeter, self.fields.get(field, b'')) if i] def vercmp(self, debq): - res = cmp(int(self.epoch()), int(debq.epoch())) + res = packagequery.cmp(int(self.epoch()), int(debq.epoch())) if res != 0: return res res = DebQuery.debvercmp(self.version(), debq.version()) - if res != None: + if res != 0: return res res = DebQuery.debvercmp(self.release(), debq.release()) return res def name(self): - return self.fields['package'] + return self.fields[b'package'] def version(self): - return self.fields['version'] + return self.fields[b'version'] def release(self): - return self.fields['release'] + return self.fields[b'release'] def epoch(self): - return self.fields['epoch'] + return self.fields[b'epoch'] def arch(self): - return self.fields['architecture'] + return self.fields[b'architecture'] def description(self): - return self.fields['description'] + return self.fields[b'description'] def path(self): return self.__path def provides(self): - return self.fields['provides'] + return self.fields[b'provides'] def requires(self): - return self.fields['depends'] + self.fields['pre_depends'] + return self.fields[b'depends'] + self.fields[b'pre_depends'] def conflicts(self): - return self.fields['conflicts'] + self.fields['breaks'] + return self.fields[b'conflicts'] + self.fields[b'breaks'] def obsoletes(self): return [] def recommends(self): - return self.fields['recommends'] + return self.fields[b'recommends'] def suggests(self): - return self.fields['suggests'] + return self.fields[b'suggests'] def supplements(self): # a control file has no notion of "supplements" return [] def enhances(self): - return self.fields['enhances'] + return self.fields[b'enhances'] def gettag(self, num): return self.fields.get(num, None) @@ -174,20 +188,31 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): """ # 32 is arbitrary - it is needed for the "longer digit string wins" handling # (found this nice approach in Build/Deb.pm (build package)) - ver1 = re.sub('(\d+)', lambda m: (32 * '0' + m.group(1))[-32:], ver1) - ver2 = re.sub('(\d+)', lambda m: (32 * '0' + m.group(1))[-32:], ver2) - vers = map(lambda x, y: (x or '', y or ''), ver1, ver2) + ver1 = re.sub(b'(\d+)', lambda m: (32 * b'0' + m.group(1))[-32:], ver1) + ver2 = re.sub(b'(\d+)', lambda m: (32 * b'0' + m.group(1))[-32:], ver2) + vers = itertools.zip_longest(ver1, ver2, fillvalue=b'') for v1, v2 in vers: if v1 == v2: continue + if not v1: + # this makes the corresponding condition in the following + # else part superfluous - keep the superfluous condition for + # now (just to ease a (hopefully) upcoming refactoring (this + # method really deserves a cleanup...)) + return -1 + if not v2: + # see above + return 1 + v1 = bytes(bytearray([v1])) + v2 = bytes(bytearray([v2])) if (v1.isalpha() and v2.isalpha()) or (v1.isdigit() and v2.isdigit()): - res = cmp(v1, v2) + res = packagequery.cmp(v1, v2) if res != 0: return res else: - if v1 == '~' or not v1: + if v1 == b'~' or not v1: return -1 - elif v2 == '~' or not v2: + elif v2 == b'~' or not v2: return 1 ord1 = ord(v1) if not (v1.isalpha() or v1.isdigit()): @@ -204,9 +229,9 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): @staticmethod def filename(name, epoch, version, release, arch): if release: - return '%s_%s-%s_%s.deb' % (name, version, release, arch) + return b'%s_%s-%s_%s.deb' % (name, version, release, arch) else: - return '%s_%s_%s.deb' % (name, version, arch) + return b'%s_%s_%s.deb' % (name, version, arch) if __name__ == '__main__': import sys @@ -218,6 +243,6 @@ if __name__ == '__main__': print(debq.name(), debq.version(), debq.release(), debq.arch()) print(debq.description()) print('##########') - print('\n'.join(debq.provides())) + print(b'\n'.join(debq.provides())) print('##########') - print('\n'.join(debq.requires())) + print(b'\n'.join(debq.requires())) |