<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css"
        integrity="sha512-SzlrxWUlpfuzQ+pcUCosxcglQRNAq/DZjVsC0lE40xsADsfeQoEypE+enwcOiGjk/bSuGGKHEyjSoQ1zVisanQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
</html>
from typing import (
    Collection,
    Generic,
    Iterable,
    Iterator,
    List,
    Mapping,
    Optional,
)

from .providers import AbstractProvider, AbstractResolver
from .structs import CT, KT, RT, DirectedGraph, IterableView

# This should be a NamedTuple, but Python 3.6 has a bug that prevents it.
# https://stackoverflow.com/a/50531189/1376863
class RequirementInformation(tuple, Generic[RT, CT]):
    requirement: RT
    parent: Optional[CT]

class Criterion(Generic[RT, CT, KT]):
    candidates: IterableView[CT]
    information: Collection[RequirementInformation[RT, CT]]
    incompatibilities: List[CT]
    @classmethod
    def from_requirement(
        cls,
        provider: AbstractProvider[RT, CT, KT],
        requirement: RT,
        parent: Optional[CT],
    ) -> Criterion[RT, CT, KT]: ...
    def iter_requirement(self) -> Iterator[RT]: ...
    def iter_parent(self) -> Iterator[Optional[CT]]: ...
    def merged_with(
        self,
        provider: AbstractProvider[RT, CT, KT],
        requirement: RT,
        parent: Optional[CT],
    ) -> Criterion[RT, CT, KT]: ...
    def excluded_of(self, candidates: List[CT]) -> Criterion[RT, CT, KT]: ...

class ResolverException(Exception): ...

class RequirementsConflicted(ResolverException, Generic[RT, CT, KT]):
    criterion: Criterion[RT, CT, KT]

class ResolutionError(ResolverException): ...

class InconsistentCandidate(ResolverException, Generic[RT, CT, KT]):
    candidate: CT
    criterion: Criterion[RT, CT, KT]

class ResolutionImpossible(ResolutionError, Generic[RT, CT]):
    causes: List[RequirementInformation[RT, CT]]

class ResolutionTooDeep(ResolutionError):
    round_count: int

# This should be a NamedTuple, but Python 3.6 has a bug that prevents it.
# https://stackoverflow.com/a/50531189/1376863
class State(tuple, Generic[RT, CT, KT]):
    mapping: Mapping[KT, CT]
    criteria: Mapping[KT, Criterion[RT, CT, KT]]
    backtrack_causes: Collection[RequirementInformation[RT, CT]]

class Resolution(Generic[RT, CT, KT]):
    def resolve(
        self, requirements: Iterable[RT], max_rounds: int
    ) -> State[RT, CT, KT]: ...

class Result(Generic[RT, CT, KT]):
    mapping: Mapping[KT, CT]
    graph: DirectedGraph[Optional[KT]]
    criteria: Mapping[KT, Criterion[RT, CT, KT]]

class Resolver(AbstractResolver, Generic[RT, CT, KT]):
    base_exception = ResolverException
    def resolve(
        self, requirements: Iterable[RT], max_rounds: int = 100
    ) -> Result[RT, CT, KT]: ...
