aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'gentoolkit/pym/gentoolkit/versionmatch.py')
-rw-r--r--gentoolkit/pym/gentoolkit/versionmatch.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/gentoolkit/pym/gentoolkit/versionmatch.py b/gentoolkit/pym/gentoolkit/versionmatch.py
new file mode 100644
index 0000000..c081de0
--- /dev/null
+++ b/gentoolkit/pym/gentoolkit/versionmatch.py
@@ -0,0 +1,134 @@
+#! /usr/bin/python
+#
+# Copyright 2009-2010 Gentoo Foundation
+# Licensed under the GNU General Public License, v2
+#
+# Copyright 2005-2007 Brian Harring <ferringb@gmail.com>
+# License: GPL2/BSD
+#
+# $Header$
+
+"""Gentoo version comparison object from pkgcore.ebuild.atom_restricts."""
+
+# =======
+# Imports
+# =======
+
+from portage.versions import vercmp
+
+from gentoolkit import errors
+from gentoolkit.cpv import CPV
+
+# =======
+# Classes
+# =======
+
+class VersionMatch(object):
+ """Gentoo version comparison object from pkgcore.ebuild.atom_restricts.
+
+ Any overriding of this class *must* maintain numerical order of
+ self.vals, see intersect for reason why. vals also must be a tuple.
+ """
+ _convert_op2int = {(-1,):"<", (-1, 0): "<=", (0,):"=",
+ (0, 1):">=", (1,):">"}
+
+ _convert_int2op = dict([(v, k) for k, v in _convert_op2int.iteritems()])
+
+ def __init__(self, cpv, op='='):
+ """Initialize a VersionMatch instance.
+
+ @type cpv: L{gentoolkit.cpv.CPV}
+ @param cpv: cpv object
+ @type op: str
+ @keyword op: operator
+ """
+
+ if not isinstance(cpv, (CPV, self.__class__)):
+ err = "cpv must be a gentoolkit.cpv.CPV "
+ err += "or gentoolkit.versionmatch.VersionMatch instance"
+ raise ValueError(err)
+ self.cpv = cpv
+ self.operator = op
+ self.version = cpv.version
+ self.revision = cpv.revision
+ self.fullversion = cpv.fullversion
+
+ if self.operator != "~" and self.operator not in self._convert_int2op:
+ raise errors.GentoolkitInvalidVersion(
+ "invalid operator '%s'" % self.operator)
+
+ if self.operator == "~":
+ if not self.version:
+ raise errors.GentoolkitInvalidVersion(
+ "for ~ op, ver must be specified")
+ self.droprevision = True
+ self.values = (0,)
+ else:
+ self.droprevision = False
+ self.values = self._convert_int2op[self.operator]
+
+ def match(self, other):
+ """See whether a passed in VersionMatch or CPV instance matches self.
+
+ Example usage:
+ >>> from gentoolkit.versionmatch import VersionMatch
+ >>> from gentoolkit.cpv import CPV
+ >>> VersionMatch(CPV('foo/bar-1.5'), op='>').match(
+ ... VersionMatch(CPV('foo/bar-2.0')))
+ True
+
+ @type other: gentoolkit.versionmatch.VersionMatch OR
+ gentoolkit.cpv.CPV
+ @param other: version to compare with self's version
+ @rtype: bool
+ """
+
+ if self.droprevision:
+ ver1, ver2 = self.version, other.version
+ else:
+ ver1, ver2 = self.fullversion, other.fullversion
+
+ return vercmp(ver2, ver1) in self.values
+
+ def __str__(self):
+ operator = self._convert_op2int[self.values]
+
+ if self.droprevision or not self.revision:
+ return "ver %s %s" % (operator, self.version)
+ return "ver-rev %s %s-%s" % (
+ operator, self.version, self.revision
+ )
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__, str(self))
+
+ @staticmethod
+ def _convert_ops(inst):
+ if inst.droprevision:
+ return inst.values
+ return tuple(sorted(set((-1, 0, 1)).difference(inst.values)))
+
+ def __eq__(self, other):
+ if self is other:
+ return True
+ if isinstance(other, self.__class__):
+ if (self.droprevision != other.droprevision or
+ self.version != other.version or
+ self.revision != other.revision):
+ return False
+ return self._convert_ops(self) == self._convert_ops(other)
+
+ return False
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __hash__(self):
+ return hash((
+ self.droprevision,
+ self.version,
+ self.revision,
+ self.values
+ ))
+
+# vim: set ts=4 sw=4 tw=79: