def fix_requires_python_marker(requires_python): from packaging.requirements import Requirement as PackagingRequirement marker_str = "" if any( requires_python.startswith(op) for op in Specifier._operators.keys()): spec_dict = defaultdict(set) # We are checking first if we have leading specifier operator # if not, we can assume we should be doing a == comparison specifierset = list(SpecifierSet(requires_python)) # for multiple specifiers, the correct way to represent that in # a specifierset is `Requirement('fakepkg; python_version<"3.0,>=2.6"')` marker_key = Variable("python_version") for spec in specifierset: operator, val = spec._spec cleaned_val = Value(val).serialize().replace('"', "") spec_dict[Op(operator).serialize()].add(cleaned_val) marker_str = " and ".join([ "{0}{1}'{2}'".format(marker_key.serialize(), op, ",".join(vals)) for op, vals in spec_dict.items() ]) marker_to_add = PackagingRequirement( "fakepkg; {0}".format(marker_str)).marker return marker_to_add
def test_specifier(op, val, expected): m = StringMarker( lhs=Variable('os_name'), op=Op(op), rhs=Value(val), ) assert str(m) == expected
def test_swap(op, val, expected): m = VersionMarker( lhs=Value(val), op=Op(op), rhs=Variable('python_version'), ) assert str(m.specifier) == expected
def test_merge(left_op, left_val, right_op, right_val, result): lm = StringMarker( lhs=Variable('os_name'), op=Op(left_op), rhs=Value(left_val), ) rm = StringMarker( lhs=Variable('os_name'), op=Op(right_op), rhs=Value(right_val), ) if result is None: with pytest.raises(TypeError): lm + rm else: merged = lm + rm assert str(merged) == result
def test_merge(left_op, left_val, right_op, right_val, result): lm = VersionMarker( lhs=Variable('python_version'), op=Op(left_op), rhs=Value(left_val), ) rm = VersionMarker( lhs=Variable('python_version'), op=Op(right_op), rhs=Value(right_val), ) if result is None: with pytest.raises(TypeError): lm + rm else: merged = lm + rm assert str(merged.specifier) == result
def __add__(self, other: 'VersionMarker'): try: spec = self.specifier + other.specifier except TypeError: return NotImplemented return type(self)( lhs=self.lhs, op=Op(value=spec.operator), rhs=Value(value=str(spec.version)), )
def _convert_single_marker(lhs: Union[Value, Variable], op: Op, rhs: Union[Value, Variable]) -> Union[Operation, BaseMarker]: var = lhs.value if type(lhs) is Variable else rhs.value if var in STRING_VARIABLES: return StringMarker(lhs=lhs, op=op, rhs=rhs) if var not in VERSION_VARIABLES: raise LookupError('unknown marker: {}'.format(var)) if op.value == 'in' and type(rhs) is Value: values = rhs.value.split() markers = [VersionMarker(lhs=lhs, op=Op('=='), rhs=Value(value)) for value in values] return OrMarker(*markers) if op.value in {'in' 'not in'}: msg = 'unsupported operation for version marker {}: {}' raise ValueError(msg.format(var, op.value)) return VersionMarker(lhs=lhs, op=op, rhs=rhs)
def _marker_reduction(marker, extra): # type: ignore """Convert internal packaging marker representation to interpretation which can be evaluated. As markers also depend on `extra' which will cause issues when evaluating marker in the solver environment, let's substitute `extra' marker with a condition which evaluates always to true. """ if isinstance(marker, str): return marker if isinstance(marker, list): result_markers = [] for nested_marker in marker: reduced_marker = _marker_reduction(nested_marker, extra) # type: ignore result_markers.append(reduced_marker) return result_markers if marker[0].value != "extra": return marker extra.add(str(marker[2])) # A special case to handle extras in markers - substitute extra with a marker which always evaluates to true: return Variable("python_version"), Op(">="), Value("0.0")