Bug 1453274 - Support esr version strings. r=rail

MozReview-Commit-ID: K7khNCzOwQK

--HG--
extra : rebase_source : 33225a5ecb879705327af505920d4db040a91d7b
This commit is contained in:
Justin Wood 2018-04-23 14:14:04 -04:00
parent 9e151c936d
commit 335012b188
2 changed files with 64 additions and 10 deletions

View File

@ -1,10 +1,46 @@
from __future__ import absolute_import
from distutils.version import StrictVersion
from distutils.version import StrictVersion, LooseVersion
import re
class ModernMozillaVersion(StrictVersion):
class MozillaVersionCompareMixin():
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 is not 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
@ -13,7 +49,7 @@ class ModernMozillaVersion(StrictVersion):
([a-zA-Z]+(\d+))?$""", re.VERBOSE)
class AncientMozillaVersion(StrictVersion):
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
@ -24,6 +60,16 @@ class AncientMozillaVersion(StrictVersion):
([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)
@ -34,6 +80,10 @@ def MozillaVersion(version):
return AncientMozillaVersion(version)
except ValueError:
pass
try:
return LooseModernMozillaVersion(version)
except ValueError:
pass
raise ValueError("Version number %s is invalid." % version)

View File

@ -48,17 +48,17 @@ ALL_VERSIONS = [ # Keep this sorted
'3.5.10',
# ... Start skipping around...
'4.0b9',
# '10.0.2esr',
# '10.0.3esr',
'10.0.2esr',
'10.0.3esr',
'32.0',
'49.0a1',
'49.0a2',
'59.0',
'60.0',
# '60.0esr',
# '60.0.1esr',
'60.0esr',
'60.0.1esr',
'60.1',
# '60.1.0esr',
'60.1esr',
'61.0',
]
@ -80,12 +80,16 @@ def test_versions_parseable(version):
assert MozillaVersion(version) is not None
def test_versions_compare(comparable_versions):
def test_versions_compare_less(comparable_versions):
"""Test that versions properly compare in order."""
smaller_version, larger_version = comparable_versions
assert MozillaVersion(smaller_version) < MozillaVersion(larger_version)
def test_versions_compare_greater(comparable_versions):
"""Test that versions properly compare in order."""
smaller_version, larger_version = comparable_versions
assert MozillaVersion(larger_version) > MozillaVersion(smaller_version)
assert MozillaVersion(larger_version) != MozillaVersion(smaller_version)
@pytest.mark.parametrize('version', ALL_VERSIONS)