def intersect(self, other: VersionConstraint) -> VersionConstraint:
        from poetry.core.semver.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, VersionRangeConstraint):
            raise ValueError(f"Unknown VersionConstraint type {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
            assert intersect_min is not None

            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 allows_all(self, other: VersionConstraint) -> bool:
        from poetry.core.semver.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, VersionRangeConstraint):
            return not other.allows_lower(self) and not other.allows_higher(self)

        raise ValueError(f"Unknown VersionConstraint type {other}.")
    def _ranges_for(
        self, constraint: VersionConstraint
    ) -> list[VersionRangeConstraint]:
        if constraint.is_empty():
            return []

        if isinstance(constraint, VersionUnion):
            return constraint.ranges

        if isinstance(constraint, VersionRangeConstraint):
            return [constraint]

        raise ValueError(f"Unknown VersionConstraint type {constraint}")
Example #4
0
    def _non_empty_term(
        self, constraint: VersionConstraint, is_positive: bool, other: Term
    ) -> Term | None:
        if constraint.is_empty():
            return None

        # when creating a new term prefer direct-reference dependencies
        dependency = (
            other.dependency
            if not self.dependency.is_direct_origin()
            and other.dependency.is_direct_origin()
            else self.dependency
        )
        return Term(dependency.with_constraint(constraint), is_positive)
Example #5
0
    def union(self, other: VersionConstraint) -> VersionConstraint:
        from poetry.core.semver.version_range import VersionRange

        if other.allows(self):
            return other

        if isinstance(other, VersionRangeConstraint):
            if self.allows(other.min):
                return VersionRange(
                    other.min,
                    other.max,
                    include_min=True,
                    include_max=other.include_max,
                )

            if self.allows(other.max):
                return VersionRange(
                    other.min,
                    other.max,
                    include_min=other.include_min,
                    include_max=True,
                )

        return VersionUnion.of(self, other)
Example #6
0
def format_python_constraint(constraint: VersionConstraint) -> str:
    """
    This helper will help in transforming
    disjunctive constraint into proper constraint.
    """
    if isinstance(constraint, Version):
        if constraint.precision >= 3:
            return f"=={str(constraint)}"

        # Transform 3.6 or 3
        if constraint.precision == 2:
            # 3.6
            constraint = parse_constraint(f"~{constraint.major}.{constraint.minor}")
        else:
            constraint = parse_constraint(f"^{constraint.major}.0")

    if not isinstance(constraint, VersionUnion):
        return str(constraint)

    formatted = []
    accepted = []

    for version in PYTHON_VERSION:
        version_constraint = parse_constraint(version)
        matches = constraint.allows_any(version_constraint)
        if not matches:
            formatted.append("!=" + version)
        else:
            accepted.append(version)

    # Checking lower bound
    low = accepted[0]

    formatted.insert(0, ">=" + ".".join(low.split(".")[:2]))

    return ", ".join(formatted)
Example #7
0
    def _non_empty_term(self, constraint: VersionConstraint,
                        is_positive: bool) -> Term | None:
        if constraint.is_empty():
            return None

        return Term(self.dependency.with_constraint(constraint), is_positive)
Example #8
0
 def allows_all(self, other: VersionConstraint) -> bool:
     return other.is_empty() or (self.allows(other) if isinstance(
         other, self.__class__) else other == self)
Example #9
0
    def difference(self,
                   other: VersionConstraint) -> Version | EmptyConstraint:
        if other.allows(self):
            return EmptyConstraint()

        return self
Example #10
0
    def intersect(self, other: VersionConstraint) -> Version | EmptyConstraint:
        if other.allows(self):
            return self

        return EmptyConstraint()
Example #11
0
 def allows_any(self, other: VersionConstraint) -> bool:
     return other.allows(self)
 def allows_all(self, other: VersionConstraint) -> bool:
     return other.is_empty()
    def difference(self, other: VersionConstraint) -> VersionConstraint:
        from poetry.core.semver.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, VersionRangeConstraint):
            if not self.allows_any(other):
                return self

            before: VersionConstraint | None
            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
                )

            after: VersionConstraint | None
            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:
                assert after is not None
                return after

            if after is None:
                return before

            return VersionUnion.of(before, after)
        elif isinstance(other, VersionUnion):
            ranges: list[VersionRangeConstraint] = []
            current: VersionRangeConstraint = 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:
                    assert isinstance(difference, VersionRangeConstraint)
                    current = difference

            if not ranges:
                return current

            return VersionUnion.of(*(ranges + [current]))

        raise ValueError(f"Unknown VersionConstraint type {other}.")