Commit 1abf3635 by Tarun Jethwani Committed by GitHub

mypy: fix poetry.mixology

Relates-to: #5017
parent fafe0b76
......@@ -120,14 +120,6 @@ module = [
'poetry.installation.executor',
'poetry.installation.installer',
'poetry.installation.pip_installer',
'poetry.mixology.assignment',
'poetry.mixology.failure',
'poetry.mixology.incompatibility',
'poetry.mixology.partial_solution',
'poetry.mixology.solutions.providers.python_requirement_solution_provider',
'poetry.mixology.solutions.solutions.python_requirement_solution',
'poetry.mixology.term',
'poetry.mixology.version_solver',
'poetry.repositories.installed_repository',
'poetry.utils.env',
]
......
......@@ -41,7 +41,7 @@ class Assignment(Term):
return self._index
@property
def cause(self) -> Incompatibility:
def cause(self) -> Incompatibility | None:
return self._cause
@classmethod
......
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import cast
from poetry.core.semver.helpers import parse_constraint
......@@ -114,8 +115,9 @@ class _Writer:
conjunction = "So," if conclusion or incompatibility == self._root else "And"
incompatibility_string = str(incompatibility)
cause = incompatibility.cause
details_for_cause = {}
cause: ConflictCause = cast(ConflictCause, incompatibility.cause)
details_for_cause: dict = {}
if isinstance(cause.conflict.cause, ConflictCause) and isinstance(
cause.other.cause, ConflictCause
):
......@@ -136,7 +138,7 @@ class _Writer:
with_line = cause.conflict
without_line = cause.other
line = conflict_line
else:
elif other_line is not None:
with_line = cause.other
without_line = cause.conflict
line = other_line
......@@ -200,7 +202,7 @@ class _Writer:
numbered=numbered,
)
elif self._is_collapsible(derived):
derived_cause: ConflictCause = derived.cause
derived_cause: ConflictCause = cast(ConflictCause, derived.cause)
if isinstance(derived_cause.conflict.cause, ConflictCause):
collapsed_derived = derived_cause.conflict
collapsed_ext = derived_cause.other
......@@ -239,7 +241,7 @@ class _Writer:
if self._derivations[incompatibility] > 1:
return False
cause: ConflictCause = incompatibility.cause
cause: ConflictCause = cast(ConflictCause, incompatibility.cause)
if isinstance(cause.conflict.cause, ConflictCause) and isinstance(
cause.other.cause, ConflictCause
):
......
......@@ -50,7 +50,7 @@ class Incompatibility:
ref = term.dependency.complete_name
if ref in by_ref:
by_ref[ref] = by_ref[ref].intersect(term)
value = by_ref[ref].intersect(term)
# If we have two terms that refer to the same package but have a
# null intersection, they're mutually exclusive, making this
......@@ -58,7 +58,8 @@ class Incompatibility:
# exclusive version ranges are incompatible. We should never derive
# an irrelevant incompatibility.
err_msg = f"Package '{ref}' is listed as a dependency of itself."
assert by_ref[ref] is not None, err_msg
assert value is not None, err_msg
by_ref[ref] = value
else:
by_ref[ref] = term
......@@ -83,23 +84,13 @@ class Incompatibility:
return self._terms
@property
def cause(
self,
) -> (
RootCause
| NoVersionsCause
| DependencyCause
| ConflictCause
| PythonCause
| PlatformCause
| PackageNotFoundCause
):
def cause(self) -> IncompatibilityCause:
return self._cause
@property
def external_incompatibilities(
self,
) -> Iterator[ConflictCause | Incompatibility]:
) -> Iterator[Incompatibility]:
"""
Returns all external incompatibilities in this incompatibility's
derivation graph.
......@@ -134,18 +125,16 @@ class Incompatibility:
assert len(self._terms) == 1
assert self._terms[0].is_positive()
cause: PythonCause = self._cause
text = f"{self._terse(self._terms[0], allow_every=True)} requires "
text += f"Python {cause.python_version}"
text += f"Python {self._cause.python_version}"
return text
elif isinstance(self._cause, PlatformCause):
assert len(self._terms) == 1
assert self._terms[0].is_positive()
cause: PlatformCause = self._cause
text = f"{self._terse(self._terms[0], allow_every=True)} requires "
text += f"platform {cause.platform}"
text += f"platform {self._cause.platform}"
return text
elif isinstance(self._cause, NoVersionsCause):
......@@ -307,7 +296,11 @@ class Incompatibility:
return "".join(buffer)
def _try_requires_through(
self, other: Incompatibility, details: dict, this_line: int, other_line: int
self,
other: Incompatibility,
details: dict,
this_line: int | None,
other_line: int | None,
) -> str | None:
if len(self._terms) == 1 or len(other.terms) == 1:
return None
......@@ -385,7 +378,11 @@ class Incompatibility:
return "".join(buffer)
def _try_requires_forbidden(
self, other: Incompatibility, details: dict, this_line: int, other_line: int
self,
other: Incompatibility,
details: dict,
this_line: int | None,
other_line: int | None,
) -> str | None:
if len(self._terms) != 1 and len(other.terms) != 1:
return None
......
......@@ -156,10 +156,10 @@ class PartialSolution:
ref = assignment.dependency.complete_name
negative_by_ref = self._negative.get(name)
old_negative = None if negative_by_ref is None else negative_by_ref.get(ref)
if old_negative is None:
term = assignment
else:
term = assignment.intersect(old_negative)
term = (
assignment if old_negative is None else assignment.intersect(old_negative)
)
assert term is not None
if term.is_positive():
if name in self._negative:
......@@ -208,7 +208,7 @@ class PartialSolution:
def satisfies(self, term: Term) -> bool:
return self.relation(term) == SetRelation.SUBSET
def relation(self, term: Term) -> int:
def relation(self, term: Term) -> str:
positive = self._positive.get(term.dependency.complete_name)
if positive is not None:
return positive.relation(term)
......
......@@ -10,6 +10,8 @@ from crashtest.contracts.has_solutions_for_exception import HasSolutionsForExcep
if TYPE_CHECKING:
from crashtest.contracts.solution import Solution
from poetry.puzzle.exceptions import SolverProblemError
class PythonRequirementSolutionProvider(HasSolutionsForException):
def can_solve(self, exception: Exception) -> bool:
......@@ -26,7 +28,7 @@ class PythonRequirementSolutionProvider(HasSolutionsForException):
return bool(m)
def get_solutions(self, exception: Exception) -> list[Solution]:
def get_solutions(self, exception: SolverProblemError) -> list[Solution]:
from poetry.mixology.solutions.solutions.python_requirement_solution import (
PythonRequirementSolution,
)
......
......@@ -6,18 +6,19 @@ from crashtest.contracts.solution import Solution
if TYPE_CHECKING:
from poetry.mixology.incompatibility_cause import PackageNotFoundCause
from poetry.mixology.failure import SolveFailure
from poetry.puzzle.exceptions import SolverProblemError
class PythonRequirementSolution(Solution):
def __init__(self, exception: PackageNotFoundCause) -> None:
def __init__(self, exception: SolverProblemError) -> None:
from poetry.core.semver.helpers import parse_constraint
from poetry.mixology.incompatibility_cause import PythonCause
self._title = "Check your dependencies Python requirement."
failure = exception.error
failure: SolveFailure = exception.error
version_solutions = []
for incompatibility in failure._incompatibility.external_incompatibilities:
if isinstance(incompatibility.cause, PythonCause):
......
......@@ -49,7 +49,7 @@ class Term:
)
@functools.lru_cache(maxsize=None)
def relation(self, other: Term) -> int:
def relation(self, other: Term) -> str:
"""
Returns the relationship between the package versions
allowed by this term and another.
......@@ -144,7 +144,7 @@ class Term:
else:
return None
def difference(self, other: Term) -> Term:
def difference(self, other: Term) -> Term | None:
"""
Returns a Term that represents packages
allowed by this term and not by the other
......
......@@ -159,7 +159,7 @@ class VersionSolver:
changed.add(str(self._propagate_incompatibility(root_cause)))
break
elif result is not None:
changed.add(result)
changed.add(str(result))
def _propagate_incompatibility(
self, incompatibility: Incompatibility
......@@ -290,6 +290,9 @@ class VersionSolver:
# than a derivation), then incompatibility is the root cause. We then
# backjump to previous_satisfier_level, where incompatibility is
# guaranteed to allow _propagate to produce more assignments.
# using assert to suppress mypy [union-attr]
assert most_recent_satisfier is not None
if (
previous_satisfier_level < most_recent_satisfier.decision_level
or most_recent_satisfier.cause is None
......
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from poetry.mixology.failure import SolveFailure
class SolverProblemError(Exception):
def __init__(self, error: Exception) -> None:
def __init__(self, error: SolveFailure) -> None:
self._error = error
super().__init__(str(error))
@property
def error(self) -> Exception:
def error(self) -> SolveFailure:
return self._error
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment