Bug#891328: python-debian: DebFile.changelog() fails to parse DebianVersion (in some cases)
Philipp Hahn
hahn at univention.de
Sat Feb 24 14:30:48 UTC 2018
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
-------------- next part --------------
#!/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()
More information about the pkg-python-debian-maint
mailing list