This repository has been archived on 2025-09-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Alicja Cięciwa cb8886666c login page
2020-10-27 12:57:58 +01:00

137 lines
4.6 KiB
Python

# -*- coding=utf-8 -*-
from __future__ import absolute_import, unicode_literals
import itertools
import operator
from packaging.specifiers import SpecifierSet, Specifier
from vistir.misc import dedup
def _tuplize_version(version):
return tuple(int(x) for x in version.split("."))
def _format_version(version):
return ".".join(str(i) for i in version)
# Prefer [x,y) ranges.
REPLACE_RANGES = {">": ">=", "<=": "<"}
def _format_pyspec(specifier):
if isinstance(specifier, str):
if not any(op in specifier for op in Specifier._operators.keys()):
specifier = "=={0}".format(specifier)
specifier = Specifier(specifier)
if specifier.operator == "==" and specifier.version.endswith(".*"):
specifier = Specifier("=={0}".format(specifier.version[:-2]))
try:
op = REPLACE_RANGES[specifier.operator]
except KeyError:
return specifier
version = specifier.version.replace(".*", "")
curr_tuple = _tuplize_version(version)
try:
next_tuple = (curr_tuple[0], curr_tuple[1] + 1)
except IndexError:
next_tuple = (curr_tuple[0], 1)
specifier = Specifier("{0}{1}".format(op, _format_version(next_tuple)))
return specifier
def _get_specs(specset):
if isinstance(specset, Specifier):
specset = str(specset)
if isinstance(specset, str):
specset = SpecifierSet(specset.replace(".*", ""))
return [
(spec._spec[0], _tuplize_version(spec._spec[1]))
for spec in getattr(specset, "_specs", [])
]
def _group_by_op(specs):
specs = [_get_specs(x) for x in list(specs)]
flattened = [(op, version) for spec in specs for op, version in spec]
specs = sorted(flattened, key=operator.itemgetter(1))
grouping = itertools.groupby(specs, key=operator.itemgetter(0))
return grouping
def cleanup_pyspecs(specs, joiner="or"):
specs = {_format_pyspec(spec) for spec in specs}
# for != operator we want to group by version
# if all are consecutive, join as a list
results = set()
for op, versions in _group_by_op(specs):
versions = [version[1] for version in versions]
versions = sorted(dedup(versions))
# if we are doing an or operation, we need to use the min for >=
# this way OR(>=2.6, >=2.7, >=3.6) picks >=2.6
# if we do an AND operation we need to use MAX to be more selective
if op in (">", ">="):
if joiner == "or":
results.add((op, _format_version(min(versions))))
else:
results.add((op, _format_version(max(versions))))
# we use inverse logic here so we will take the max value if we are
# using OR but the min value if we are using AND
elif op in ("<=", "<"):
if joiner == "or":
results.add((op, _format_version(max(versions))))
else:
results.add((op, _format_version(min(versions))))
# leave these the same no matter what operator we use
elif op in ("!=", "==", "~="):
version_list = sorted(
"{0}".format(_format_version(version))
for version in versions
)
version = ", ".join(version_list)
if len(version_list) == 1:
results.add((op, version))
elif op == "!=":
results.add(("not in", version))
elif op == "==":
results.add(("in", version))
else:
specifier = SpecifierSet(",".join(sorted(
"{0}".format(op, v) for v in version_list
)))._specs
for s in specifier:
results &= (specifier._spec[0], specifier._spec[1])
else:
if len(version) == 1:
results.add((op, version))
else:
specifier = SpecifierSet("{0}".format(version))._specs
for s in specifier:
results |= (specifier._spec[0], specifier._spec[1])
return results
def pyspec_from_markers(marker):
if marker._markers[0][0] != 'python_version':
return
op = marker._markers[0][1].value
version = marker._markers[0][2].value
specset = set()
if op == "in":
specset.update(
Specifier("=={0}".format(v.strip()))
for v in version.split(",")
)
elif op == "not in":
specset.update(
Specifier("!={0}".format(v.strip()))
for v in version.split(",")
)
else:
specset.add(Specifier("".join([op, version])))
if specset:
return specset
return None