Hacked By AnonymousFox
from typing import List
import semver
from .empty_constraint import EmptyConstraint
from .version_constraint import VersionConstraint
from .version_union import VersionUnion
class VersionRange(VersionConstraint):
def __init__(
self,
min=None,
max=None,
include_min=False,
include_max=False,
always_include_max_prerelease=False,
):
full_max = max
if (
always_include_max_prerelease
and not include_max
and not full_max.is_prerelease()
and not full_max.build
and (min is None or not min.is_prerelease() or not min.equals_without_prerelease(full_max))
):
full_max = full_max.first_prerelease
self._min = min
self._max = max
self._full_max = full_max
self._include_min = include_min
self._include_max = include_max
@property
def min(self):
return self._min
@property
def max(self):
return self._max
@property
def full_max(self):
return self._full_max
@property
def include_min(self):
return self._include_min
@property
def include_max(self):
return self._include_max
def is_empty(self):
return False
def is_any(self):
return self._min is None and self._max is None
def allows(self, other): # type: (semver.Version) -> bool
if self._min is not None:
if other < self._min:
return False
if not self._include_min and other == self._min:
return False
if self._max is not None:
if other > self._max:
return False
if not self._include_max and other == self._max:
return False
return True
def allows_all(self, other): # type: (VersionConstraint) -> bool
from .version import Version
if other.is_empty():
return True
if isinstance(other, Version):
return self.allows(other)
if isinstance(other, VersionUnion):
return all([self.allows_all(constraint) for constraint in other.ranges])
if isinstance(other, VersionRange):
return not other.allows_lower(self) and not other.allows_higher(self)
raise ValueError("Unknown VersionConstraint type {}.".format(other))
def allows_any(self, other): # type: (VersionConstraint) -> bool
from .version import Version
if other.is_empty():
return False
if isinstance(other, Version):
return self.allows(other)
if isinstance(other, VersionUnion):
return any([self.allows_any(constraint) for constraint in other.ranges])
if isinstance(other, VersionRange):
return not other.is_strictly_lower(self) and not other.is_strictly_higher(self)
raise ValueError("Unknown VersionConstraint type {}.".format(other))
def intersect(self, other): # type: (VersionConstraint) -> VersionConstraint
from .version import Version
if other.is_empty():
return other
if isinstance(other, VersionUnion):
return other.intersect(self)
# A range and a Version just yields the version if it's in the range.
if isinstance(other, Version):
if self.allows(other):
return other
return EmptyConstraint()
if not isinstance(other, VersionRange):
raise ValueError("Unknown VersionConstraint type {}.".format(other))
if self.allows_lower(other):
if self.is_strictly_lower(other):
return EmptyConstraint()
intersect_min = other.min
intersect_include_min = other.include_min
else:
if other.is_strictly_lower(self):
return EmptyConstraint()
intersect_min = self._min
intersect_include_min = self._include_min
if self.allows_higher(other):
intersect_max = other.max
intersect_include_max = other.include_max
else:
intersect_max = self._max
intersect_include_max = self._include_max
if intersect_min is None and intersect_max is None:
return VersionRange()
# If the range is just a single version.
if intersect_min == intersect_max:
# Because we already verified that the lower range isn't strictly
# lower, there must be some overlap.
assert intersect_include_min and intersect_include_max
return intersect_min
# If we got here, there is an actual range.
return VersionRange(intersect_min, intersect_max, intersect_include_min, intersect_include_max)
def union(self, other): # type: (VersionConstraint) -> VersionConstraint
from .version import Version
if isinstance(other, Version):
if self.allows(other):
return self
if other == self.min:
return VersionRange(self.min, self.max, include_min=True, include_max=self.include_max)
if other == self.max:
return VersionRange(self.min, self.max, include_min=self.include_min, include_max=True)
return VersionUnion.of(self, other)
if isinstance(other, VersionRange):
# If the two ranges don't overlap, we won't be able to create a single
# VersionRange for both of them.
edges_touch = (self.max == other.min and (self.include_max or other.include_min)) or (
self.min == other.max and (self.include_min or other.include_max)
)
if not edges_touch and not self.allows_any(other):
return VersionUnion.of(self, other)
if self.allows_lower(other):
union_min = self.min
union_include_min = self.include_min
else:
union_min = other.min
union_include_min = other.include_min
if self.allows_higher(other):
union_max = self.max
union_include_max = self.include_max
else:
union_max = other.max
union_include_max = other.include_max
return VersionRange(
union_min,
union_max,
include_min=union_include_min,
include_max=union_include_max,
)
return VersionUnion.of(self, other)
def difference(self, other): # type: (VersionConstraint) -> VersionConstraint
from .version import Version
if other.is_empty():
return self
if isinstance(other, Version):
if not self.allows(other):
return self
if other == self.min:
if not self.include_min:
return self
return VersionRange(self.min, self.max, False, self.include_max)
if other == self.max:
if not self.include_max:
return self
return VersionRange(self.min, self.max, self.include_min, False)
return VersionUnion.of(
VersionRange(self.min, other, self.include_min, False),
VersionRange(other, self.max, False, self.include_max),
)
elif isinstance(other, VersionRange):
if not self.allows_any(other):
return self
if not self.allows_lower(other):
before = None
elif self.min == other.min:
before = self.min
else:
before = VersionRange(self.min, other.min, self.include_min, not other.include_min)
if not self.allows_higher(other):
after = None
elif self.max == other.max:
after = self.max
else:
after = VersionRange(other.max, self.max, not other.include_max, self.include_max)
if before is None and after is None:
return EmptyConstraint()
if before is None:
return after
if after is None:
return before
return VersionUnion.of(before, after)
elif isinstance(other, VersionUnion):
ranges = [] # type: List[VersionRange]
current = self
for range in other.ranges:
# Skip any ranges that are strictly lower than [current].
if range.is_strictly_lower(current):
continue
# If we reach a range strictly higher than [current], no more ranges
# will be relevant so we can bail early.
if range.is_strictly_higher(current):
break
difference = current.difference(range)
if difference.is_empty():
return EmptyConstraint()
elif isinstance(difference, VersionUnion):
# If [range] split [current] in half, we only need to continue
# checking future ranges against the latter half.
ranges.append(difference.ranges[0])
current = difference.ranges[-1]
else:
current = difference
if not ranges:
return current
return VersionUnion.of(*(ranges + [current]))
raise ValueError("Unknown VersionConstraint type {}.".format(other))
def allows_lower(self, other): # type: (VersionRange) -> bool
if self.min is None:
return other.min is not None
if other.min is None:
return False
if self.min < other.min:
return True
if self.min > other.min:
return False
return self.include_min and not other.include_min
def allows_higher(self, other): # type: (VersionRange) -> bool
if self.max is None:
return other.max is not None
if other.max is None:
return False
if self.max < other.max:
return False
if self.max > other.max:
return True
return self.include_max and not other.include_max
def is_strictly_lower(self, other): # type: (VersionRange) -> bool
if self.max is None or other.min is None:
return False
if self.full_max < other.min:
return True
if self.full_max > other.min:
return False
return not self.include_max or not other.include_min
def is_strictly_higher(self, other): # type: (VersionRange) -> bool
return other.is_strictly_lower(self)
def is_adjacent_to(self, other): # type: (VersionRange) -> bool
if self.max != other.min:
return False
return self.include_max and not other.include_min or not self.include_max and other.include_min
def __eq__(self, other):
if not isinstance(other, VersionRange):
return False
return (
self._min == other.min
and self._max == other.max
and self._include_min == other.include_min
and self._include_max == other.include_max
)
def __lt__(self, other):
return self._cmp(other) < 0
def __le__(self, other):
return self._cmp(other) <= 0
def __gt__(self, other):
return self._cmp(other) > 0
def __ge__(self, other):
return self._cmp(other) >= 0
def _cmp(self, other): # type: (VersionRange) -> int
if self.min is None:
if other.min is None:
return self._compare_max(other)
return -1
elif other.min is None:
return 1
result = self.min._cmp(other.min)
if result != 0:
return result
if self.include_min != other.include_min:
return -1 if self.include_min else 1
return self._compare_max(other)
def _compare_max(self, other): # type: (VersionRange) -> int
if self.max is None:
if other.max is None:
return 0
return 1
elif other.max is None:
return -1
result = self.max._cmp(other.max)
if result != 0:
return result
if self.include_max != other.include_max:
return 1 if self.include_max else -1
return 0
def __str__(self):
text = ""
if self.min is not None:
text += ">=" if self.include_min else ">"
text += self.min.text
if self.max is not None:
if self.min is not None:
text += ","
text += "{}{}".format("<=" if self.include_max else "<", self.max.text)
if self.min is None and self.max is None:
return "*"
return text
def __repr__(self):
return "<VersionRange ({})>".format(str(self))
def __hash__(self):
return hash((self.min, self.max, self.include_min, self.include_max))
Hacked By AnonymousFox1.0, Coded By AnonymousFox