kopia lustrzana https://github.com/jupyterhub/repo2docker
Tidying up
rodzic
6e2a718d15
commit
b3451d3bc7
|
@ -1,15 +1,16 @@
|
||||||
# This file implements the julia-specific logic for handling SemVer (Semantic
|
"""
|
||||||
# Versioning) strings in .toml files.
|
Julia specific handling of SemVer strings
|
||||||
#
|
|
||||||
# It uses the python "semver" package to do most version string comparisons, but
|
It uses the python "semver" package to do most version string comparisons, but
|
||||||
# the places where julia's SemVer handling differs from the semver package have
|
the places where julia's SemVer handling differs from the semver package have
|
||||||
# been implemented directly.
|
been implemented directly.
|
||||||
#
|
"""
|
||||||
# Here, we use tuples to represent a Version, and functors as "matchers". The matcher
|
|
||||||
# functors take a version string and return true if it passes its constraints.
|
# We use tuples to represent a Version, and functors as "matchers". The
|
||||||
|
# matcher functors take a version string and return True if it passes its
|
||||||
|
# constraints.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
import semver
|
import semver
|
||||||
|
|
||||||
|
@ -29,70 +30,6 @@ def str_to_version(vstr):
|
||||||
return tuple([int(n) for n in vstr.split(".")])
|
return tuple([int(n) for n in vstr.split(".")])
|
||||||
|
|
||||||
|
|
||||||
# --- Matcher interface -------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractMatcher:
|
|
||||||
def match(self, v):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SemverMatcher(AbstractMatcher):
|
|
||||||
""" Match a version tuple to a given constraint_str using the `semver` package. """
|
|
||||||
|
|
||||||
def __init__(self, constraint_str):
|
|
||||||
self.constraint_str = constraint_str
|
|
||||||
|
|
||||||
def match(self, v):
|
|
||||||
while len(v) < 3:
|
|
||||||
v = v + (0,)
|
|
||||||
v_str = ".".join(map(str, v))
|
|
||||||
return semver.match(v_str, self.constraint_str)
|
|
||||||
|
|
||||||
def __eq__(self, rhs):
|
|
||||||
return self.constraint_str == rhs.constraint_str
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.constraint_str
|
|
||||||
|
|
||||||
|
|
||||||
# --- Custom matcher for julia-specific SemVer handling: ---------
|
|
||||||
class Exclusivity(Enum):
|
|
||||||
EXCLUSIVE = 1
|
|
||||||
INCLUSIVE = 2
|
|
||||||
|
|
||||||
|
|
||||||
class VersionRange(AbstractMatcher):
|
|
||||||
"""Match a version tuple between lower and upper bounds"""
|
|
||||||
|
|
||||||
def __init__(self, lower, upper, upper_exclusivity):
|
|
||||||
self.lower = lower
|
|
||||||
self.upper = upper
|
|
||||||
self.upper_exclusivity = upper_exclusivity
|
|
||||||
|
|
||||||
def match(self, v):
|
|
||||||
if self.upper_exclusivity == Exclusivity.EXCLUSIVE:
|
|
||||||
return self.lower <= v < self.upper
|
|
||||||
else:
|
|
||||||
return self.lower <= v <= self.upper
|
|
||||||
|
|
||||||
def __eq__(self, rhs):
|
|
||||||
return (
|
|
||||||
self.lower == rhs.lower
|
|
||||||
and self.upper == rhs.upper
|
|
||||||
and self.upper_exclusivity == rhs.upper_exclusivity
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return (
|
|
||||||
"["
|
|
||||||
+ ".".join(map(str, self.lower))
|
|
||||||
+ "-"
|
|
||||||
+ ".".join(map(str, self.upper))
|
|
||||||
+ (")" if self.upper_exclusivity == Exclusivity.EXCLUSIVE else "]")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
def major(v):
|
def major(v):
|
||||||
return v[0]
|
return v[0]
|
||||||
|
@ -106,13 +43,10 @@ def patch(v):
|
||||||
return v[2] if len(v) >= 3 else 0
|
return v[2] if len(v) >= 3 else 0
|
||||||
|
|
||||||
|
|
||||||
# --- main constraint parser function ------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def create_semver_matcher(constraint_str):
|
def create_semver_matcher(constraint_str):
|
||||||
"""
|
"""Create a matcher that can be used to match version tuples
|
||||||
Returns a derived-class instance of AbstractMatcher that matches version
|
|
||||||
tuples against the provided constraint_str.
|
Version tuples are matched against the provided `constraint_str`.
|
||||||
"""
|
"""
|
||||||
constraint_str = constraint_str.strip()
|
constraint_str = constraint_str.strip()
|
||||||
first_digit = re.search(r"\d", constraint_str)
|
first_digit = re.search(r"\d", constraint_str)
|
||||||
|
@ -129,17 +63,18 @@ def create_semver_matcher(constraint_str):
|
||||||
# Also, julia treats pre-1.0 releases specially, as if the first
|
# Also, julia treats pre-1.0 releases specially, as if the first
|
||||||
# non-zero number is actually a major number:
|
# non-zero number is actually a major number:
|
||||||
# https://docs.julialang.org/en/latest/stdlib/Pkg/#Caret-specifiers-1
|
# https://docs.julialang.org/en/latest/stdlib/Pkg/#Caret-specifiers-1
|
||||||
# So we need to handle it separately by bumping the first non-zero number.
|
# So we need to handle it separately by bumping the first non-zero
|
||||||
|
# enumber.
|
||||||
for i, n in enumerate(constraint):
|
for i, n in enumerate(constraint):
|
||||||
if (
|
if (
|
||||||
n != 0 or i == len(constraint) - 1
|
n != 0 or i == len(constraint) - 1
|
||||||
): # (using the last existing number handles situations like "^0.0" or "^0")
|
): # (using the last existing number handles situations like "^0.0" or "^0")
|
||||||
upper = constraint[0:i] + (n + 1,)
|
upper = constraint[0:i] + (n + 1,)
|
||||||
break
|
break
|
||||||
return VersionRange(constraint, upper, Exclusivity.EXCLUSIVE)
|
return VersionRange(constraint, upper, True)
|
||||||
else:
|
else:
|
||||||
return VersionRange(
|
return VersionRange(
|
||||||
constraint, (major(constraint) + 1,), Exclusivity.EXCLUSIVE
|
constraint, (major(constraint) + 1,), True
|
||||||
)
|
)
|
||||||
|
|
||||||
# '~' matching (only allowed to bump the last present number by one)
|
# '~' matching (only allowed to bump the last present number by one)
|
||||||
|
@ -147,7 +82,7 @@ def create_semver_matcher(constraint_str):
|
||||||
return VersionRange(
|
return VersionRange(
|
||||||
constraint,
|
constraint,
|
||||||
constraint[:-1] + (constraint[-1] + 1,),
|
constraint[:-1] + (constraint[-1] + 1,),
|
||||||
Exclusivity.INCLUSIVE,
|
upper_exclusivity=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Use semver package's comparisons for everything else:
|
# Use semver package's comparisons for everything else:
|
||||||
|
@ -165,3 +100,59 @@ def create_semver_matcher(constraint_str):
|
||||||
constraint_str = re.sub(r"(^|\b)=\b", "==", constraint_str)
|
constraint_str = re.sub(r"(^|\b)=\b", "==", constraint_str)
|
||||||
|
|
||||||
return SemverMatcher(constraint_str)
|
return SemverMatcher(constraint_str)
|
||||||
|
|
||||||
|
|
||||||
|
class SemverMatcher:
|
||||||
|
"""Match a version tuple to a given `constraint_str`
|
||||||
|
|
||||||
|
The matching is handled via the `semver` package.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, constraint_str):
|
||||||
|
self.constraint_str = constraint_str
|
||||||
|
|
||||||
|
def match(self, v):
|
||||||
|
while len(v) < 3:
|
||||||
|
v = v + (0,)
|
||||||
|
v_str = ".".join(map(str, v))
|
||||||
|
return semver.match(v_str, self.constraint_str)
|
||||||
|
|
||||||
|
def __eq__(self, rhs):
|
||||||
|
return self.constraint_str == rhs.constraint_str
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.constraint_str
|
||||||
|
|
||||||
|
|
||||||
|
class VersionRange:
|
||||||
|
"""Match a version tuple between lower and upper bounds
|
||||||
|
|
||||||
|
`upper_exclusivity` specifies if the upper bound is inclusive or exclusive.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, lower, upper, upper_exclusivity):
|
||||||
|
self.lower = lower
|
||||||
|
self.upper = upper
|
||||||
|
self.upper_exclusivity = upper_exclusivity
|
||||||
|
|
||||||
|
def match(self, v):
|
||||||
|
if self.upper_exclusivity:
|
||||||
|
return self.lower <= v < self.upper
|
||||||
|
else:
|
||||||
|
return self.lower <= v <= self.upper
|
||||||
|
|
||||||
|
def __eq__(self, rhs):
|
||||||
|
return (
|
||||||
|
self.lower == rhs.lower
|
||||||
|
and self.upper == rhs.upper
|
||||||
|
and self.upper_exclusivity == rhs.upper_exclusivity
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return (
|
||||||
|
"["
|
||||||
|
+ ".".join(map(str, self.lower))
|
||||||
|
+ "-"
|
||||||
|
+ ".".join(map(str, self.upper))
|
||||||
|
+ (")" if self.upper_exclusivity else "]")
|
||||||
|
)
|
||||||
|
|
Ładowanie…
Reference in New Issue