import attr
import re
from mozilla_version.errors import PatternNotMatchedError
from mozilla_version.parser import get_value_matched_by_regex
from mozilla_version.gecko import (
GeckoVersion, FirefoxVersion, DeveditionVersion, FennecVersion, ThunderbirdVersion
)
_VALID_ENOUGH_BALROG_RELEASE_PATTERN = re.compile(
r"^(?P<product>[a-z]+)-(?P<version>.+)$", re.IGNORECASE
)
_SUPPORTED_PRODUCTS = {
'firefox': FirefoxVersion,
'devedition': DeveditionVersion,
'fennec': FennecVersion,
'thunderbird': ThunderbirdVersion,
}
def _supported_product(string):
product = string.lower()
if product not in _SUPPORTED_PRODUCTS:
raise PatternNotMatchedError(string, pattern='unknown product')
return product
def _products_must_be_identical(method):
def checker(this, other):
if this.product != other.product:
raise ValueError('Cannot compare "{}" and "{}"'.format(this.product, other.product))
return method(this, other)
return checker
@attr.s(frozen=True, cmp=False)
class BalrogReleaseName(object):
product = attr.ib(type=str, converter=_supported_product)
version = attr.ib(type=GeckoVersion)
def __attrs_post_init__(self):
if self.version.build_number is None:
raise PatternNotMatchedError(self, pattern='build_number must exist')
@classmethod
def parse(cls, release_string):
regex_matches = _VALID_ENOUGH_BALROG_RELEASE_PATTERN.match(release_string)
if regex_matches is None:
raise PatternNotMatchedError(release_string, _VALID_ENOUGH_BALROG_RELEASE_PATTERN)
product = get_value_matched_by_regex('product', regex_matches, release_string)
try:
VersionClass = _SUPPORTED_PRODUCTS[product.lower()]
except KeyError:
raise PatternNotMatchedError(release_string, pattern='unknown product')
version_string = get_value_matched_by_regex('version', regex_matches, release_string)
version = VersionClass.parse(version_string)
return cls(product, version)
def __str__(self):
version_string = str(self.version).replace('build', '-build')
return '{}-{}'.format(self.product, version_string)
@_products_must_be_identical
def __eq__(self, other):
return self.version == other.version
@_products_must_be_identical
def __ne__(self, other):
return self.version != other.version
@_products_must_be_identical
def __lt__(self, other):
return self.version < other.version
@_products_must_be_identical
def __le__(self, other):
return self.version <= other.version
@_products_must_be_identical
def __gt__(self, other):
return self.version > other.version
@_products_must_be_identical
def __ge__(self, other):
return self.version >= other.version