Last active
August 29, 2015 14:07
-
-
Save mottosso/f4cb1c636fae3fc63ab0 to your computer and use it in GitHub Desktop.
Library versioning example
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
"""Library versioning using the default Python syntax | |
Example: | |
>>> is_compatible("pyblish<=1", (0, 9, 0)) | |
True | |
>>> is_compatible("pyblish>=1.1, <2.1", (2, 0, 0)) | |
True | |
""" | |
import re | |
import operator | |
def is_compatible(requirement, version): | |
"""Return whether or not `requirement` is compatible with `version` | |
Example: | |
>>> is_compatible("pyblish<=1", (0, 9, 0)) | |
True | |
>>> is_compatible("pyblish>=1, <1.3", (1, 2, 0)) | |
True | |
>>> is_compatible("pyblish>=0.9.9", (1, 0, 0)) | |
True | |
>>> is_compatible("pyblish>=1.1, <2.1", (2, 0, 0)) | |
True | |
>>> is_compatible("pyblish==1.0.0", (1, 0, 0)) | |
True | |
>>> is_compatible("pyblish==1.0.0", (1, 0, 1)) | |
False | |
""" | |
results = list() | |
for operator_string, requirement_string in parse_requirements(requirement): | |
operator = operators[operator_string] | |
required = string_to_tuple(requirement_string) | |
result = operator(version, required) | |
results.append(result) | |
return all(results) | |
def parse_requirements(line): | |
"""From pkg_utils.parse_requirements | |
Example: | |
>>> parse_requirements("pyblish==1.0.0") | |
[('==', '1.0.0')] | |
>>> parse_requirements("pyblish>=1.1.0") | |
[('>=', '1.1.0')] | |
>>> parse_requirements("pyblish>=1.1.0, <1.2") | |
[('>=', '1.1.0'), ('<', '1.2')] | |
""" | |
LINE_END = re.compile(r"\s*(#.*)?$") | |
DISTRO = re.compile(r"\s*((\w|[-.])+)") | |
VERSION = re.compile(r"\s*(<=?|>=?|==|!=)\s*((\w|[-.])+)") | |
COMMA = re.compile(r"\s*,") | |
match = DISTRO.match(line) | |
p = match.end() | |
specs = list() | |
while not LINE_END.match(line, p): | |
match = VERSION.match(line, p) | |
if not match: | |
raise ValueError( | |
"Expected version spec in", | |
line, "at", line[p:]) | |
specs.append(match.group(*(1, 2))) | |
p = match.end() | |
match = COMMA.match(line, p) | |
if match: | |
p = match.end() # Skip comma | |
elif not LINE_END.match(line, p): | |
raise ValueError( | |
"Expected ',' or end-of-list in", | |
line, "at", line[p:]) | |
return specs | |
def string_to_tuple(version): | |
"""Convert version as string to tuple | |
Example: | |
>>> string_to_tuple("1.0.0") | |
(1, 0, 0) | |
>>> string_to_tuple("2.5") | |
(2, 5) | |
""" | |
return tuple(map(int, version.split("."))) | |
operators = {"<": operator.lt, | |
"<=": operator.le, | |
"==": operator.eq, | |
"!=": operator.ne, | |
">=": operator.ge, | |
">": operator.gt} | |
if __name__ == '__main__': | |
import doctest | |
doctest.testmod() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment