Created
March 14, 2017 06:57
-
-
Save siddharthg/96c7ee61db664f48be2ab4add17bbefd to your computer and use it in GitHub Desktop.
Python Version String (Semantic Versioning)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__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