from collections.abc import Callable
from typing import Any, Generic, TypeAlias, TypeVar

__all__ = ("PromiseProxy", "Proxy", "maybe_evaluate", "try_import")

from typing_extensions import Self, override

_T = TypeVar("_T")
_R = TypeVar("_R")

_Getter: TypeAlias = Callable[[_T], _R]
_Setter: TypeAlias = Callable[[_T, _R], None]

def maybe_evaluate(obj: Any) -> Any: ...
def try_import(module: str, default: _T = ...) -> Any | _T: ...

class class_property(Generic[_T, _R]):
    __get: _Getter[_T, _R]
    __set: _Setter[_T, _R] | None
    def __init__(
        self,
        getter: _Getter[_T, _R] | None = None,
        setter: _Setter[_T, _R] | None = None,
    ) -> None: ...
    def __get__(self, obj: _T | None, type: type[_T] | None = None) -> _R: ...
    def __set__(self, obj: _T | None, value: _R) -> Self: ...
    def setter(self, setter: _Setter[_T, _R]) -> Self: ...

class Proxy(Generic[_T]):
    def __init__(
        self,
        local: Callable[[], _T],
        args: tuple[Any, ...] | None = ...,
        kwargs: dict[str, Any] | None = ...,
        name: str | None = ...,
        __doc__: str | None = ...,
    ) -> None: ...
    def _get_current_object(self) -> _T: ...
    # All the dunder methods that proxy to the wrapped object
    def __abs__(self) -> Any: ...
    def __add__(self, other: Any) -> Any: ...
    def __and__(self, other: Any) -> Any: ...
    def __bool__(self) -> bool: ...
    def __call__(self, *a: Any, **kw: Any) -> Any: ...
    def __coerce__(self, other: Any) -> Any: ...
    def __complex__(self) -> complex: ...
    def __contains__(self, i: Any) -> bool: ...
    def __delitem__(self, key: Any) -> None: ...
    def __divmod__(self, other: Any) -> Any: ...
    def __enter__(self) -> Any: ...
    def __exit__(self, *a: object, **kw: Any) -> Any: ...
    def __float__(self) -> float: ...
    def __floordiv__(self, other: Any) -> Any: ...
    def __ge__(self, other: Any) -> bool: ...
    def __getitem__(self, i: Any) -> Any: ...
    def __gt__(self, other: Any) -> bool: ...
    def __hex__(self) -> str: ...
    def __index__(self) -> int: ...
    def __int__(self) -> int: ...
    def __invert__(self) -> Any: ...
    def __iter__(self) -> Any: ...
    def __le__(self, other: Any) -> bool: ...
    def __len__(self) -> int: ...
    def __lt__(self, other: Any) -> bool: ...
    def __mod__(self, other: Any) -> Any: ...
    def __mul__(self, other: Any) -> Any: ...
    @override
    def __ne__(self, other: object) -> bool: ...
    def __neg__(self) -> Any: ...
    def __oct__(self) -> str: ...
    def __or__(self, other: Any) -> Any: ...
    def __pos__(self) -> Any: ...
    def __pow__(self, other: Any) -> Any: ...
    @override
    def __reduce__(self) -> tuple[Any, ...]: ...
    def __rshift__(self, other: Any) -> Any: ...
    def __lshift__(self, other: Any) -> Any: ...
    def __setitem__(self, key: Any, value: Any) -> None: ...
    def __sub__(self, other: Any) -> Any: ...
    def __truediv__(self, other: Any) -> Any: ...
    def __xor__(self, other: Any) -> Any: ...
    @property
    def __name__(self) -> str: ...

class PromiseProxy(Proxy[_T]):
    def __init__(
        self,
        local: Callable[[], _T],
        args: tuple[Any, ...] | None = ...,
        kwargs: dict[str, Any] | None = ...,
        name: str | None = ...,
        __doc__: str | None = ...,
    ) -> None: ...
    def __evaluate__(
        self,
        _clean: tuple[str, ...] = ("_Proxy__local", "_Proxy__args", "_Proxy__kwargs"),
    ) -> _T: ...
    def __evaluated__(self) -> bool: ...
    def __maybe_evaluate__(self) -> _T: ...
    @property
    def __pending__(self) -> bool: ...
    def __then__(self, fun: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: ...
