mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[enh] Implement the intersection of package version Specifier class
This commit is contained in:
parent
55debefd56
commit
afda4a9c90
1 changed files with 82 additions and 17 deletions
|
@ -98,6 +98,7 @@ class Specifier(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, spec):
|
def __init__(self, spec):
|
||||||
|
if isinstance(spec, basestring):
|
||||||
match = self._regex.search(spec)
|
match = self._regex.search(spec)
|
||||||
if not match:
|
if not match:
|
||||||
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
|
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
|
||||||
|
@ -106,6 +107,10 @@ class Specifier(object):
|
||||||
match.group("relation").strip(),
|
match.group("relation").strip(),
|
||||||
match.group("version").strip(),
|
match.group("version").strip(),
|
||||||
)
|
)
|
||||||
|
elif isinstance(spec, self.__class__):
|
||||||
|
self._spec = spec._spec
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Specifier({1!r})>".format(str(self))
|
return "<Specifier({1!r})>".format(str(self))
|
||||||
|
@ -138,6 +143,9 @@ class Specifier(object):
|
||||||
|
|
||||||
return self._spec != other._spec
|
return self._spec != other._spec
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
return self.intersection(other)
|
||||||
|
|
||||||
def _get_relation(self, op):
|
def _get_relation(self, op):
|
||||||
return getattr(self, "_compare_{0}".format(self._relations[op]))
|
return getattr(self, "_compare_{0}".format(self._relations[op]))
|
||||||
|
|
||||||
|
@ -167,6 +175,49 @@ class Specifier(object):
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return self.contains(item)
|
return self.contains(item)
|
||||||
|
|
||||||
|
def intersection(self, other):
|
||||||
|
"""Make the intersection of two specifiers
|
||||||
|
|
||||||
|
Return a new `SpecifierSet` with version specifier(s) common to the
|
||||||
|
specifier and the other.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> Specifier('>= 2.2') & '>> 2.2.1' == '>> 2.2.1'
|
||||||
|
>>> Specifier('>= 2.2') & '<< 2.3' == '>= 2.2, << 2.3'
|
||||||
|
|
||||||
|
"""
|
||||||
|
if isinstance(other, basestring):
|
||||||
|
try:
|
||||||
|
other = self.__class__(other)
|
||||||
|
except InvalidSpecifier:
|
||||||
|
return NotImplemented
|
||||||
|
elif not isinstance(other, self.__class__):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
# store spec parts for easy access
|
||||||
|
rel1, v1 = self.relation, self.version
|
||||||
|
rel2, v2 = other.relation, other.version
|
||||||
|
result = []
|
||||||
|
|
||||||
|
if other == self:
|
||||||
|
result = [other]
|
||||||
|
elif rel1 == '=':
|
||||||
|
result = [self] if v1 in other else None
|
||||||
|
elif rel2 == '=':
|
||||||
|
result = [other] if v2 in self else None
|
||||||
|
elif v1 == v2:
|
||||||
|
result = [other if rel1[1] == '=' else self]
|
||||||
|
elif v2 in self or v1 in other:
|
||||||
|
is_self_greater = version_compare(v1, v2) > 0
|
||||||
|
if rel1[0] == rel2[0]:
|
||||||
|
if rel1[0] == '>':
|
||||||
|
result = [self if is_self_greater else other]
|
||||||
|
else:
|
||||||
|
result = [other if is_self_greater else self]
|
||||||
|
else:
|
||||||
|
result = [self, other]
|
||||||
|
return SpecifierSet(result if result is not None else '')
|
||||||
|
|
||||||
def contains(self, item):
|
def contains(self, item):
|
||||||
return self._get_relation(self.relation)(item, self.version)
|
return self._get_relation(self.relation)(item, self.version)
|
||||||
|
|
||||||
|
@ -181,7 +232,9 @@ class SpecifierSet(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, specifiers):
|
def __init__(self, specifiers):
|
||||||
specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
|
if isinstance(specifiers, basestring):
|
||||||
|
specifiers = [s.strip() for s in specifiers.split(",")
|
||||||
|
if s.strip()]
|
||||||
|
|
||||||
parsed = set()
|
parsed = set()
|
||||||
for specifier in specifiers:
|
for specifier in specifiers:
|
||||||
|
@ -198,15 +251,8 @@ class SpecifierSet(object):
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self._specs)
|
return hash(self._specs)
|
||||||
|
|
||||||
def __and__(self, other):
|
def __or__(self, other):
|
||||||
if isinstance(other, basestring):
|
return self.union(other)
|
||||||
other = SpecifierSet(other)
|
|
||||||
elif not isinstance(other, SpecifierSet):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
specifier = SpecifierSet()
|
|
||||||
specifier._specs = frozenset(self._specs | other._specs)
|
|
||||||
return specifiers
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, basestring):
|
if isinstance(other, basestring):
|
||||||
|
@ -237,6 +283,25 @@ class SpecifierSet(object):
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return self.contains(item)
|
return self.contains(item)
|
||||||
|
|
||||||
|
def union(self, other):
|
||||||
|
"""Make the union of two specifiers set
|
||||||
|
|
||||||
|
Return a new `SpecifierSet` with version specifiers from the set
|
||||||
|
and the other.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> SpecifierSet('>= 2.2') | '<< 2.3' == '>= 2.2, << 2.3'
|
||||||
|
|
||||||
|
"""
|
||||||
|
if isinstance(other, basestring):
|
||||||
|
other = SpecifierSet(other)
|
||||||
|
elif not isinstance(other, SpecifierSet):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
specifiers = SpecifierSet([])
|
||||||
|
specifiers._specs = frozenset(self._specs | other._specs)
|
||||||
|
return specifiers
|
||||||
|
|
||||||
def contains(self, item):
|
def contains(self, item):
|
||||||
return all(
|
return all(
|
||||||
s.contains(item)
|
s.contains(item)
|
||||||
|
|
Loading…
Add table
Reference in a new issue