Author: fw Date: 2006-06-15 18:17:18 +0000 (Thu, 15 Jun 2006) New Revision: 4236 Modified: lib/python/debian_support.py lib/python/security_db.py Log: * lib/python/debian_support.py (Version): Implement using apt_pkg if APT is available. (version_compare): Add. * lib/python/security_db.py (DB._initFunctions): Directly invoke debian_support.version_compare. Modified: lib/python/debian_support.py ==================================================================--- lib/python/debian_support.py 2006-06-15 14:21:06 UTC (rev 4235) +++ lib/python/debian_support.py 2006-06-15 18:17:18 UTC (rev 4236) @@ -22,6 +22,12 @@ import sha import types +try: + import apt_pkg + __have_apt_pkg = True +except ImportError: + __have_apt_pkg = False + class ParseError(Exception): """An exception which is used to signal a parse failure. @@ -52,74 +58,101 @@ file.write("%s:%d: %s\n" % (self.filename, self.lineno, self.msg)) file.flush() -letterValue = [None] * 256 -def initLetterValue(): - c = 0 - for x in range(ord(''A''), ord(''Z'') + 1): - letterValue[x] = chr(c) - c += 1 - for x in range(ord(''a''), ord(''z'') + 1): - letterValue[x] = chr(c) - c += 1 - for x in "+-.:": - letterValue[ord(x)] = chr(c) - c += 1 -initLetterValue() -del initLetterValue +if __have_apt_pkg: + class Version: + """Version class which uses the original APT comparison algorithm.""" -class Version: - """This class implements Debian version numbers.""" + def __init__(self, version): + """Creates a new Version object.""" + assert type(version) == types.StringType, `version` + assert version <> "" + self.__asString = version - def __init__(self, version): - """Creates a new Version object.""" - assert type(version) == types.StringType, `version` - assert version <> "" - self.__asString = version - self.__parsed = self.__parse(version) + def __str__(self): + return self.__asString - def __str__(self): - return self.__asString + def __repr__(self): + return ''Version(%s)'' % `self.__asString` - def __repr__(self): - return ''Version(%s)'' % `self.__asString` + def __cmp__(self, other): + return apt_pkg.VersionCompare(self.__asString, other.__asString) - def __cmp__(self, other): - """Compares two versions. - This method implements the algorithm in the Debian Policy.""" - return cmp(self.__parsed, other.__parsed) + version_compare = apt_pkg.VersionCompare + apt_pkg.init() - def __parse(self, v, regexp=\ - re.compile(r''^(?:(\d+):)?([A-Za-z0-9.+:-]+?)'' - + r''(?:-([A-Za-z0-9.+]+))?$'')): - match = regexp.match(v) - if match is None: - raise ValueError, "invalid Debian version string" - (epoch, upstream, debian) = match.groups() - if epoch is None: - epoch = 0 - else: - epoch = int(epoch) - return (epoch, self.__parse_1(upstream), self.__parse_1(debian)) +else: + letterValue = [None] * 256 + def initLetterValue(): + c = 0 + for x in range(ord(''A''), ord(''Z'') + 1): + letterValue[x] = chr(c) + c += 1 + for x in range(ord(''a''), ord(''z'') + 1): + letterValue[x] = chr(c) + c += 1 + for x in "+-.:": + letterValue[ord(x)] = chr(c) + c += 1 + initLetterValue() + del initLetterValue - def __parse_1(self, x, non_digits=re.compile(r''^([^0-9]*)(.*)$''), - digits=re.compile(r''^([0-9]*)(.*)$'')): - l = [] - while x is not None and x <> '''': - (nd, x) = non_digits.match(x).groups() - (d, x) = digits.match(x).groups() - nd_l = [] - for ch in nd: - nd_l.append(letterValue[ord(ch)]) - nd = ''''.join(nd_l) - if d == '''': - d = 0 + class Version: + """This class implements Debian version numbers.""" + + def __init__(self, version): + """Creates a new Version object.""" + assert type(version) == types.StringType, `version` + assert version <> "" + self.__asString = version + self.__parsed = self.__parse(version) + + def __str__(self): + return self.__asString + + def __repr__(self): + return ''Version(%s)'' % `self.__asString` + + def __cmp__(self, other): + """Compares two versions. + + This method implements the algorithm in the Debian Policy.""" + return cmp(self.__parsed, other.__parsed) + + def __parse(self, v, regexp=\ + re.compile(r''^(?:(\d+):)?([A-Za-z0-9.+:-]+?)'' + + r''(?:-([A-Za-z0-9.+]+))?$'')): + match = regexp.match(v) + if match is None: + raise ValueError, "invalid Debian version string" + (epoch, upstream, debian) = match.groups() + if epoch is None: + epoch = 0 else: - d = int(d) - l.append(nd) - l.append(d) - return l + epoch = int(epoch) + return (epoch, self.__parse_1(upstream), self.__parse_1(debian)) + def __parse_1(self, x, non_digits=re.compile(r''^([^0-9]*)(.*)$''), + digits=re.compile(r''^([0-9]*)(.*)$'')): + l = [] + while x is not None and x <> '''': + (nd, x) = non_digits.match(x).groups() + (d, x) = digits.match(x).groups() + nd_l = [] + for ch in nd: + nd_l.append(letterValue[ord(ch)]) + nd = ''''.join(nd_l) + if d == '''': + d = 0 + else: + d = int(d) + l.append(nd) + l.append(d) + return l + + def version_compare(a,b): + return cmp(Version(a), Version(b)) + class PackageFile: """A Debian package file. Modified: lib/python/security_db.py ==================================================================--- lib/python/security_db.py 2006-06-15 14:21:06 UTC (rev 4235) +++ lib/python/security_db.py 2006-06-15 18:17:18 UTC (rev 4236) @@ -455,11 +455,7 @@ return release self.db.createscalarfunction("release_name", release_name, 3) - # This is slower than the version_linear_order table, but - # often more convenient to use in queries. - def collate_version(a, b): - return debian_support.Version(a).__cmp__(debian_support.Version(b)) - self.db.createcollation("version", collate_version) + self.db.createcollation("version", debian_support.version_compare) def filePrint(self, filename): """Returns a fingerprint string for filename."""