from q2_sdk.core.cli.textui import colored, puts_err
[docs]
class VersionComponent:
def __init__(self, component_str: str):
"""
Major/Minor/Patch component of Version.
May contain numberic and alpha portion (1.2.3a)
"""
self.numeric, self.alpha = self._get_detailed_component(component_str)
def _get_detailed_component(self, version_bit):
version_bit = str(version_bit)
alpha_index = len(version_bit)
for i, val in enumerate(version_bit):
if not val.isnumeric():
alpha_index = i
break
numeric = version_bit[:alpha_index]
alpha = version_bit[alpha_index:]
return int(numeric), alpha
[docs]
class Version:
VERSION_CAPTURE = "[\"'](.*)['\"]"
def __init__(self, version_string):
"""Easy Version string (1.2.3) object for comparison/display"""
version_string = version_string.replace(".tar.gz", "")
version = version_string.rstrip().split(".")
while len(version) < 3:
version.append("0")
self.major = version[0]
self.minor = version[1]
self.patch = version[2].replace("-rc", "")
self.pre_release = "0"
if len(version) == 4:
self.pre_release = version[3]
self.detailed_major = VersionComponent(self.major)
self.detailed_minor = VersionComponent(self.minor)
self.detailed_patch = VersionComponent(self.patch)
self.detailed_pre_release = VersionComponent(self.pre_release)
def __hash__(self):
return hash(self.version_string)
@property
def version_string(self):
"""major.minor.patch"""
version = f"{self.major}.{self.minor}.{self.patch}"
if int(self.pre_release) != 0:
version = f"{self.major}.{self.minor}.{self.patch}-rc.{self.pre_release}"
return version
def __lt__(self, other):
if isinstance(other, str):
other = Version(other)
for component in (
"detailed_major",
"detailed_minor",
"detailed_patch",
"detailed_pre_release",
):
this_comp = getattr(self, component)
other_comp = getattr(other, component)
if this_comp.numeric > other_comp.numeric:
return False
if this_comp.numeric == other_comp.numeric:
if this_comp.alpha and not other_comp.alpha:
return True
if other_comp.alpha and not this_comp.alpha:
return False
if this_comp.alpha < other_comp.alpha:
return True
if this_comp.numeric < other_comp.numeric:
return True
return False
def __le__(self, other):
if isinstance(other, str):
other = Version(other)
return self < other or self == other
def __ge__(self, other):
if isinstance(other, str):
other = Version(other)
return self > other or self == other
def __gt__(self, other):
if isinstance(other, str):
other = Version(other)
for component in (
"detailed_major",
"detailed_minor",
"detailed_patch",
"detailed_pre_release",
):
this_comp = getattr(self, component)
other_comp = getattr(other, component)
if this_comp.numeric < other_comp.numeric:
return False
if this_comp.numeric == other_comp.numeric:
if other_comp.alpha and not this_comp.alpha:
return True
if this_comp.alpha and not other_comp.alpha:
return False
if this_comp.alpha > other_comp.alpha:
return True
elif this_comp.numeric > other_comp.numeric:
return True
return False
def __eq__(self, other):
if isinstance(other, str):
other = Version(other)
return self.version_string == other.version_string
def __repr__(self):
return f"Version({self.version_string})"
def __str__(self):
return self.version_string
[docs]
def bump_version(self, tag: str):
"""
Increment Version
:param tag: Major/Minor/Patch
"""
tag = tag.lower()
try:
ver = int(getattr(self, tag))
ver += 1
setattr(self, tag, str(ver))
if tag == "major":
self.minor = 0
self.patch = 0
self.pre_release = 0
elif tag == "minor":
self.patch = 0
self.pre_release = 0
elif tag == "patch":
self.pre_release = 0
except AttributeError as error:
print(str(error))
puts_err(colored.red("Invalid version tag {}".format(tag)))
return str(self)