Skip to content

Commit

Permalink
Merge pull request #135 from sarugaku/modern-typing
Browse files Browse the repository at this point in the history
feat: modern typing
  • Loading branch information
frostming authored Oct 31, 2023
2 parents 6df10d7 + fd1dd99 commit 044ab9f
Show file tree
Hide file tree
Showing 12 changed files with 368 additions and 412 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ['setuptools>=36.2.2', 'wheel>=0.28.0']
requires = ['setuptools>=62', 'wheel']

[tool.black]
line-length = 79
Expand Down
3 changes: 2 additions & 1 deletion src/resolvelib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
__version__ = "1.0.2.dev0"


from .providers import AbstractProvider, AbstractResolver
from .providers import AbstractProvider
from .reporters import BaseReporter
from .resolvers import (
AbstractResolver,
InconsistentCandidate,
RequirementsConflicted,
ResolutionError,
Expand Down
11 changes: 0 additions & 11 deletions src/resolvelib/__init__.pyi

This file was deleted.

74 changes: 38 additions & 36 deletions src/resolvelib/providers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
class AbstractProvider(object):
from __future__ import annotations

from typing import (
TYPE_CHECKING,
Generic,
Iterable,
Iterator,
Mapping,
Sequence,
)

from .structs import CT, KT, RT, Matches, RequirementInformation

if TYPE_CHECKING:
from typing import Any, Protocol

class Preference(Protocol):
def __lt__(self, __other: Any) -> bool:
...


class AbstractProvider(Generic[RT, CT, KT]):
"""Delegate class to provide the required interface for the resolver."""

def identify(self, requirement_or_candidate):
def identify(self, requirement_or_candidate: RT | CT) -> KT:
"""Given a requirement or candidate, return an identifier for it.
This is used to identify, e.g. whether two requirements
Expand All @@ -12,13 +33,13 @@ def identify(self, requirement_or_candidate):

def get_preference(
self,
identifier,
resolutions,
candidates,
information,
backtrack_causes,
):
"""Produce a sort key for the given requirement based on preference.
identifier: KT,
resolutions: Mapping[KT, CT],
candidates: Mapping[KT, Iterator[CT]],
information: Mapping[KT, Iterator[RequirementInformation[RT, CT]]],
backtrack_causes: Sequence[RequirementInformation[RT, CT]],
) -> Preference:
"""Produce a sort key for given requirement based on preference.
The preference is defined as "I think this requirement should be
resolved first". The lower the return value is, the more preferred
Expand Down Expand Up @@ -62,7 +83,12 @@ def get_preference(
"""
raise NotImplementedError

def find_matches(self, identifier, requirements, incompatibilities):
def find_matches(
self,
identifier: KT,
requirements: Mapping[KT, Iterator[RT]],
incompatibilities: Mapping[KT, Iterator[CT]],
) -> Matches:
"""Find all possible candidates that satisfy the given constraints.
:param identifier: An identifier as returned by ``identify()``. All
Expand Down Expand Up @@ -92,7 +118,7 @@ def find_matches(self, identifier, requirements, incompatibilities):
"""
raise NotImplementedError

def is_satisfied_by(self, requirement, candidate):
def is_satisfied_by(self, requirement: RT, candidate: CT) -> bool:
"""Whether the given requirement can be satisfied by a candidate.
The candidate is guaranteed to have been generated from the
Expand All @@ -103,34 +129,10 @@ def is_satisfied_by(self, requirement, candidate):
"""
raise NotImplementedError

def get_dependencies(self, candidate):
def get_dependencies(self, candidate: CT) -> Iterable[RT]:
"""Get dependencies of a candidate.
This should return a collection of requirements that `candidate`
specifies as its dependencies.
"""
raise NotImplementedError


class AbstractResolver(object):
"""The thing that performs the actual resolution work."""

base_exception = Exception

def __init__(self, provider, reporter):
self.provider = provider
self.reporter = reporter

def resolve(self, requirements, **kwargs):
"""Take a collection of constraints, spit out the resolution result.
This returns a representation of the final resolution state, with one
guaranteed attribute ``mapping`` that contains resolved candidates as
values. The keys are their respective identifiers.
:param requirements: A collection of constraints.
:param kwargs: Additional keyword arguments that subclasses may accept.
:raises: ``self.base_exception`` or its subclass.
"""
raise NotImplementedError
44 changes: 0 additions & 44 deletions src/resolvelib/providers.pyi

This file was deleted.

37 changes: 28 additions & 9 deletions src/resolvelib/reporters.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
class BaseReporter(object):
from __future__ import annotations

from typing import Generic

from .structs import (
CT,
KT,
RT,
Collection,
Criterion,
RequirementInformation,
State,
)


class BaseReporter(Generic[RT, CT, KT]):
"""Delegate class to provider progress reporting for the resolver."""

def starting(self):
def starting(self) -> None:
"""Called before the resolution actually starts."""

def starting_round(self, index):
def starting_round(self, index: int) -> None:
"""Called before each round of resolution starts.
The index is zero-based.
"""

def ending_round(self, index, state):
def ending_round(self, index: int, state: State[RT, CT, KT]) -> None:
"""Called before each round of resolution ends.
This is NOT called if the resolution ends at this round. Use `ending`
if you want to report finalization. The index is zero-based.
"""

def ending(self, state):
def ending(self, state: State[RT, CT, KT]) -> None:
"""Called before the resolution ends successfully."""

def adding_requirement(self, requirement, parent):
def adding_requirement(self, requirement: RT, parent: CT | None) -> None:
"""Called when adding a new requirement into the resolve criteria.
:param requirement: The additional requirement to be applied to filter
Expand All @@ -30,14 +45,18 @@ def adding_requirement(self, requirement, parent):
requirements passed in from ``Resolver.resolve()``.
"""

def resolving_conflicts(self, causes):
def resolving_conflicts(
self, causes: Collection[RequirementInformation[RT, CT]]
) -> None:
"""Called when starting to attempt requirement conflict resolution.
:param causes: The information on the collision that caused the backtracking.
"""

def rejecting_candidate(self, criterion, candidate):
def rejecting_candidate(
self, criterion: Criterion[RT, CT], candidate: CT
) -> None:
"""Called when rejecting a candidate during backtracking."""

def pinning(self, candidate):
def pinning(self, candidate: CT) -> None:
"""Called when adding a candidate to the potential solution."""
11 changes: 0 additions & 11 deletions src/resolvelib/reporters.pyi

This file was deleted.

Loading

0 comments on commit 044ab9f

Please sign in to comment.