Skip to content

Commit

Permalink
mypy: fix poetry.mixology
Browse files Browse the repository at this point in the history
Relates-to: #5017
  • Loading branch information
tarun-jethwani committed Apr 27, 2022
1 parent fafe0b7 commit 1abf363
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 48 deletions.
8 changes: 0 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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',
]
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/mixology/assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def index(self) -> int:
return self._index

@property
def cause(self) -> Incompatibility:
def cause(self) -> Incompatibility | None:
return self._cause

@classmethod
Expand Down
12 changes: 7 additions & 5 deletions src/poetry/mixology/failure.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import cast

from poetry.core.semver.helpers import parse_constraint

Expand Down Expand Up @@ -114,8 +115,9 @@ def _visit(
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
):
Expand All @@ -136,7 +138,7 @@ def _visit(
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
Expand Down Expand Up @@ -200,7 +202,7 @@ def _visit(
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
Expand Down Expand Up @@ -239,7 +241,7 @@ def _is_collapsible(self, incompatibility: Incompatibility) -> bool:
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
):
Expand Down
37 changes: 17 additions & 20 deletions src/poetry/mixology/incompatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,16 @@ def __init__(self, terms: list[Term], cause: IncompatibilityCause) -> None:
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
# incompatibility irrelevant, since we already know that mutually
# 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

Expand All @@ -83,23 +84,13 @@ def terms(self) -> list[Term]:
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.
Expand Down Expand Up @@ -134,18 +125,16 @@ def __str__(self) -> str:
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):
Expand Down Expand Up @@ -307,7 +296,11 @@ def _try_requires_both(
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
Expand Down Expand Up @@ -385,7 +378,11 @@ def _try_requires_through(
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
Expand Down
10 changes: 5 additions & 5 deletions src/poetry/mixology/partial_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@ def _register(self, assignment: Assignment) -> None:
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:
Expand Down Expand Up @@ -208,7 +208,7 @@ def satisfier(self, term: Term) -> Assignment:
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
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:
Expand All @@ -26,7 +28,7 @@ def can_solve(self, exception: Exception) -> bool:

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,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@


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):
Expand Down
4 changes: 2 additions & 2 deletions src/poetry/mixology/term.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def satisfies(self, other: Term) -> bool:
)

@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.
Expand Down Expand Up @@ -144,7 +144,7 @@ def intersect(self, other: Term) -> Term | None:
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
Expand Down
5 changes: 4 additions & 1 deletion src/poetry/mixology/version_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def _propagate(self, package: str) -> None:
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
Expand Down Expand Up @@ -290,6 +290,9 @@ def _resolve_conflict(self, incompatibility: Incompatibility) -> Incompatibility
# 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
Expand Down
10 changes: 8 additions & 2 deletions src/poetry/puzzle/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
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


Expand Down

0 comments on commit 1abf363

Please sign in to comment.