Skip to content

Instantly share code, notes, and snippets.

@siddharthg
Created March 14, 2017 06:57
Show Gist options
  • Save siddharthg/96c7ee61db664f48be2ab4add17bbefd to your computer and use it in GitHub Desktop.
Save siddharthg/96c7ee61db664f48be2ab4add17bbefd to your computer and use it in GitHub Desktop.
Python Version String (Semantic Versioning)
__author__ = "Siddharth"
class Version(str):
def __new__(cls, data=''):
is_none = data is None
o = super(Version, cls).__new__(cls, None if is_none else data.lower())
o._is_none = is_none
return o
@property
def is_none(self):
return self._is_none
@classmethod
def compare(cls, a, b):
"""
Numeric identifiers always have lower precedence than non-numeric
identifiers. A larger set of pre-release fields has a higher pre-
cedence than a smaller set, if all of the preceding identifiers a
-re equal.
Example:
None < 1.0.0.alpha < 1.0.0.alpha.1 < 1.0.0.alpha.beta
< 1.0.0.beta < 1.0.0.beta.2 < 1.0.0.beta.11
< 1.0.0.rc.1 < 1.0.0 < 1.1.0
:type a: Version
:type b: Version
:return: 0 if a == b, 1 if a > b, -1 if a < b
:rtype: int
"""
def string_to_int(value):
try:
return int(value), False
except Exception as e:
return value, True
if a.is_none and b.is_none:
return 0
if a.is_none:
return -1
if b.is_none:
return 1
a_parts = a.split('.')
b_parts = b.split('.')
a_has_str = False
b_has_str = False
size = min(len(a_parts), len(b_parts))
# Compare element be element till size is similar
for i in range(size):
this, a_str = string_to_int(a_parts[i])
that, b_str = string_to_int(b_parts[i])
if this > that:
return 1 # 1.0.2 > 1.0.3
if this < that:
return -1 # 1.0.5.6 < 1.0.5.10
a_has_str = a_has_str or a_str
b_has_str = b_has_str or b_str
if len(a_parts) > len(b_parts):
if b_has_str:
return 1 # 1.0.0.alpha.beta > 1.0.0.alpha
for i in range(size, len(a_parts)):
this, a_str = string_to_int(a_parts[i])
a_has_str = a_has_str or a_str
if not a_has_str:
return 1 # 1.0.0.1 > 1.0.0
return -1 # 1.0.0.alpha < 1.0.0
elif len(a_parts) < len(b_parts):
if a_has_str:
return -1 # 1.0.0.alpha < 1.0.0.alpha.beta
for i in range(size, len(b_parts)):
this, b_str = string_to_int(b_parts[i])
b_has_str = b_has_str or b_str
if not b_has_str:
return -1 # 1.0.0 < 1.0.0.1
return 1 # 1.0.0 > 1.0.0.alpha
return 0
def __eq__(self, other):
other = other if isinstance(other, Version) else Version(other)
return super(Version, self).__eq__(other)
def __gt__(self, other):
other = other if isinstance(other, Version) else Version(other)
return self.compare(self, other) == 1
def __lt__(self, other):
other = other if isinstance(other, Version) else Version(other)
return self.compare(self, other) == -1
def __ne__(self, other):
return not self.__eq__(other)
def __le__(self, other):
return self.__eq__(other) or self.__lt__(other)
def __ge__(self, other):
return self.__eq__(other) or self.__gt__(other)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment