Package: python-debian Version: 0.1.30 Severity: normal Dear fellow Maintainer,
* What led up to the situation? I wrote a small Python tool to comapre the debian/changelog of two Debian binary package files. It fails on "apache2-suexec-custom" as currently available in Debian-Sid. * What exactly did you do (or not do) that was effective (or ineffective)? >apt download apache2-suexec-custom >python -c 'from debian.debfile import DebFile >from sys import argv >for block in DebFile(argv[1]).changelog(): > print(block.version)' apache2-suexec-custom_*.deb * What was the outcome of this action? >2.4.29-2 ... >2.0.37-1 >Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/usr/lib/python2.7/dist-packages/debian/changelog.py", line 103, in > _get_version > return Version(self._raw_version) > File "/usr/lib/python2.7/dist-packages/debian/debian_support.py", line 213, > in __init__ > super(AptPkgVersion, self).__init__(version) > File "/usr/lib/python2.7/dist-packages/debian/debian_support.py", line 111, > in __init__ > self.full_version = version > File "/usr/lib/python2.7/dist-packages/debian/debian_support.py", line 137, > in __setattr__ > self._set_full_version(str(value)) > File "/usr/lib/python2.7/dist-packages/debian/debian_support.py", line 116, > in _set_full_version > raise ValueError("Invalid version string %r" % version) >ValueError: Invalid version string '2.0.37+cvs.JCW_PRE2_2037-1' The underscore character '_' is not valid in debian/debian_support.py:105 > 105 "(?P<upstream_version>[A-Za-z0-9.+:~-]+?)" * What outcome did you expect instead? No traceback. Please travel back in time and fix the version number of "apache2-suexec-custom" before it gets uploaded to Debian ;-) Seriously: I see several options - add a LazyVersion like from debian.debian_support import Version class NonConformantVersion(Version): re_valid_version = re.compile( r"^((?P<epoch>\d+):)?" "(?P<upstream_version>[A-Z_a-z0-9.+:~-]+?)" "(-(?P<debian_revision>[A-Za-z0-9+.~]+))?$") import debian.changelog debian.changelog.Version = NonConformantVersion - add an option to ignore invalid/unparseable changelog blocks -- System Information: Debian Release: 9.3 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.9.0-5-amd64 (SMP w/4 CPU cores) Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8), LANGUAGE=de:en_US (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages python-debian depends on: ii python 2.7.13-2 ii python-chardet 2.3.0-2 ii python-six 1.10.0-3 Versions of packages python-debian recommends: ii python-apt 1.4.0~beta3 Versions of packages python-debian suggests: ii gpgv 2.1.18-8~deb9u1 -- no debconf information
#!/usr/bin/python2.7 """ Compare Debian package changelogs """ from __future__ import print_function from optparse import OptionParser from debian.debfile import DebFile, DebError from debian.debian_support import Version import debian.changelog from difflib import unified_diff import re # Work-around Debian Bug allowing '_' in version string # /usr/lib/python2.7/dist-packages/debian/debian_support.py:103 class NonConformantVersion(Version): re_valid_version = re.compile( r"^((?P<epoch>\d+):)?" r"(?P<upstream_version>[A-Z_a-z0-9.+:~-]+?)" r"(-(?P<debian_revision>[A-Za-z0-9+.~]+))?$") debian.changelog.Version = NonConformantVersion class DiffError(Exception): pass def load(deb): try: debfile = DebFile(deb) changelog = debfile.changelog() return changelog except (DebError, EnvironmentError): raise DiffError(deb) def render(changelog, common_version): for block in changelog: yield '{0.version} [{0.date}] {0.author}:'.format(block) for change in block.changes(): yield change if block.version == common_version: break def diff(old_deb, new_deb): old_changelog = load(old_deb) old_versions = set(block.version for block in old_changelog) new_changelog = load(new_deb) new_versions = set(block.version for block in new_changelog) common_version = max(old_versions & new_versions) old = list(render(old_changelog, common_version)) new = list(render(new_changelog, common_version)) return unified_diff(old, new, old_deb, new_deb, lineterm='') def main(): usage = '%prog <1.deb> <2.deb>' parser = OptionParser(usage=usage, description=__doc__) opt, args = parser.parse_args() try: old_deb, new_deb = args except ValueError: parser.error('Expecting exactly 2 Debian binary package files') for line in diff(old_deb, new_deb): print(line) if __name__ == '__main__': main()