summaryrefslogtreecommitdiffstats
path: root/python/mozrelease/mozrelease/versions.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozrelease/mozrelease/versions.py')
-rw-r--r--python/mozrelease/mozrelease/versions.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/python/mozrelease/mozrelease/versions.py b/python/mozrelease/mozrelease/versions.py
new file mode 100644
index 0000000000..e3e47d4e4a
--- /dev/null
+++ b/python/mozrelease/mozrelease/versions.py
@@ -0,0 +1,114 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import re
+from distutils.version import StrictVersion
+
+from looseversion import LooseVersion
+
+
+class MozillaVersionCompareMixin:
+ def __cmp__(self, other):
+ # We expect this function to never be called.
+ raise AssertionError()
+
+ def _cmp(self, other):
+ has_esr = set()
+ if isinstance(other, LooseModernMozillaVersion) and str(other).endswith("esr"):
+ # If other version ends with esr, coerce through MozillaVersion ending up with
+ # a StrictVersion if possible
+ has_esr.add("other")
+ other = MozillaVersion(str(other)[:-3]) # strip ESR from end of string
+ if isinstance(self, LooseModernMozillaVersion) and str(self).endswith("esr"):
+ # If our version ends with esr, coerce through MozillaVersion ending up with
+ # a StrictVersion if possible
+ has_esr.add("self")
+ self = MozillaVersion(str(self)[:-3]) # strip ESR from end of string
+ if isinstance(other, LooseModernMozillaVersion) or isinstance(
+ self, LooseModernMozillaVersion
+ ):
+ # If we're still LooseVersion for self or other, run LooseVersion compare
+ # Being sure to pass through Loose Version type first
+ val = LooseVersion._cmp(
+ LooseModernMozillaVersion(str(self)),
+ LooseModernMozillaVersion(str(other)),
+ )
+ else:
+ # No versions are loose, therefore we can use StrictVersion
+ val = StrictVersion._cmp(self, other)
+ if has_esr.isdisjoint(set(["other", "self"])) or has_esr.issuperset(
+ set(["other", "self"])
+ ):
+ # If both had esr string or neither, then _cmp() was accurate
+ return val
+ elif val != 0:
+ # cmp is accurate here even if esr is present in only 1 compare, since
+ # versions are not equal
+ return val
+ elif "other" in has_esr:
+ return -1 # esr is not greater than non esr
+ return 1 # non esr is greater than esr
+
+
+class ModernMozillaVersion(MozillaVersionCompareMixin, StrictVersion):
+ """A version class that is slightly less restrictive than StrictVersion.
+ Instead of just allowing "a" or "b" as prerelease tags, it allows any
+ alpha. This allows us to support the once-shipped "3.6.3plugin1" and
+ similar versions."""
+
+ version_re = re.compile(
+ r"""^(\d+) \. (\d+) (\. (\d+))?
+ ([a-zA-Z]+(\d+))?$""",
+ re.VERBOSE,
+ )
+
+
+class AncientMozillaVersion(MozillaVersionCompareMixin, StrictVersion):
+ """A version class that is slightly less restrictive than StrictVersion.
+ Instead of just allowing "a" or "b" as prerelease tags, it allows any
+ alpha. This allows us to support the once-shipped "3.6.3plugin1" and
+ similar versions.
+ It also supports versions w.x.y.z by transmuting to w.x.z, which
+ is useful for versions like 1.5.0.x and 2.0.0.y"""
+
+ version_re = re.compile(
+ r"""^(\d+) \. (\d+) \. \d (\. (\d+))
+ ([a-zA-Z]+(\d+))?$""",
+ re.VERBOSE,
+ )
+
+
+class LooseModernMozillaVersion(MozillaVersionCompareMixin, LooseVersion):
+ """A version class that is more restrictive than LooseVersion.
+ This class reduces the valid strings to "esr", "a", "b" and "rc" in order
+ to support esr. StrictVersion requires a trailing number after all strings."""
+
+ component_re = re.compile(r"(\d+ | a | b | rc | esr | \.)", re.VERBOSE)
+
+ def __repr__(self):
+ return "LooseModernMozillaVersion ('%s')" % str(self)
+
+
+def MozillaVersion(version):
+ try:
+ return ModernMozillaVersion(version)
+ except ValueError:
+ pass
+ try:
+ if version.count(".") == 3:
+ return AncientMozillaVersion(version)
+ except ValueError:
+ pass
+ try:
+ return LooseModernMozillaVersion(version)
+ except ValueError:
+ pass
+ raise ValueError("Version number %s is invalid." % version)
+
+
+def getPrettyVersion(version):
+ version = re.sub(r"a([0-9]+)$", r" Alpha \1", version)
+ version = re.sub(r"b([0-9]+)$", r" Beta \1", version)
+ version = re.sub(r"rc([0-9]+)$", r" RC \1", version)
+ return version