Skip to content

Commit

Permalink
feat: modern typing
Browse files Browse the repository at this point in the history
Signed-off-by: Frost Ming <[email protected]>
  • Loading branch information
frostming committed Aug 22, 2023
1 parent 77b256c commit 1e913e0
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 411 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.

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

from collections.abc import Mapping, Sequence
from typing import TYPE_CHECKING, Generic, Iterable, Iterator

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

if TYPE_CHECKING:
from _typeshed import SupportsRichComparison


class AbstractProvider(Generic[KT, RT, CT]):
"""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, return an identifier for it.
This is used to identify a requirement, e.g. whether two requirements
Expand All @@ -11,12 +22,12 @@ def identify(self, requirement_or_candidate):

def get_preference(
self,
identifier,
resolutions,
candidates,
information,
backtrack_causes,
):
identifier: KT,
resolutions: Mapping[KT, CT],
candidates: Mapping[KT, Iterator[CT]],
information: Mapping[KT, Iterator[RequirementInformation[RT, CT]]],
backtrack_causes: Sequence[RequirementInformation[RT, CT]],
) -> SupportsRichComparison:
"""Produce a sort key for given requirement based on preference.
The preference is defined as "I think this requirement should be
Expand Down Expand Up @@ -60,7 +71,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()``. This
Expand Down Expand Up @@ -89,7 +105,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 @@ -100,34 +116,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
guarenteed 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.

28 changes: 19 additions & 9 deletions src/resolvelib/reporters.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
class BaseReporter(object):
from collections.abc import Collection
from typing import Generic

from .structs import CT, KT, RT, Criterion, RequirementInformation, State


class BaseReporter(Generic[KT, RT, CT]):
"""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[KT, RT, CT]) -> 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[KT, RT, CT]) -> 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 +36,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 1e913e0

Please sign in to comment.