from _weakrefset import WeakSet as WeakSet
from typing import Any, Callable, Generic, Iterable, Iterator, List, Mapping, MutableMapping, Tuple, Type, TypeVar, overload

from _weakref import (
    CallableProxyType as CallableProxyType,
    ProxyType as ProxyType,
    ReferenceType as ReferenceType,
    getweakrefcount as getweakrefcount,
    getweakrefs as getweakrefs,
    proxy as proxy,
    ref as ref,
)
from exceptions import ReferenceError as ReferenceError

_S = TypeVar("_S")
_T = TypeVar("_T")
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")

ProxyTypes: Tuple[Type[Any], ...]

class WeakValueDictionary(MutableMapping[_KT, _VT]):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, __other: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
    def __len__(self) -> int: ...
    def __getitem__(self, k: _KT) -> _VT: ...
    def __setitem__(self, k: _KT, v: _VT) -> None: ...
    def __delitem__(self, v: _KT) -> None: ...
    def has_key(self, key: object) -> bool: ...
    def __contains__(self, o: object) -> bool: ...
    def __iter__(self) -> Iterator[_KT]: ...
    def __str__(self) -> str: ...
    def copy(self) -> WeakValueDictionary[_KT, _VT]: ...
    def keys(self) -> List[_KT]: ...
    def values(self) -> List[_VT]: ...
    def items(self) -> List[Tuple[_KT, _VT]]: ...
    def iterkeys(self) -> Iterator[_KT]: ...
    def itervalues(self) -> Iterator[_VT]: ...
    def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ...
    def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ...
    def valuerefs(self) -> List[KeyedRef[_KT, _VT]]: ...

class KeyedRef(ref[_T], Generic[_KT, _T]):
    key: _KT
    # This __new__ method uses a non-standard name for the "cls" parameter
    def __new__(type, ob: _T, callback: Callable[[_T], Any], key: _KT) -> KeyedRef[_KT, _T]: ...  # type: ignore
    def __init__(self, ob: _T, callback: Callable[[_T], Any], key: _KT) -> None: ...

class WeakKeyDictionary(MutableMapping[_KT, _VT]):
    @overload
    def __init__(self, dict: None = ...) -> None: ...
    @overload
    def __init__(self, dict: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]]) -> None: ...
    def __len__(self) -> int: ...
    def __getitem__(self, k: _KT) -> _VT: ...
    def __setitem__(self, k: _KT, v: _VT) -> None: ...
    def __delitem__(self, v: _KT) -> None: ...
    def has_key(self, key: object) -> bool: ...
    def __contains__(self, o: object) -> bool: ...
    def __iter__(self) -> Iterator[_KT]: ...
    def __str__(self) -> str: ...
    def copy(self) -> WeakKeyDictionary[_KT, _VT]: ...
    def keys(self) -> List[_KT]: ...
    def values(self) -> List[_VT]: ...
    def items(self) -> List[Tuple[_KT, _VT]]: ...
    def iterkeys(self) -> Iterator[_KT]: ...
    def itervalues(self) -> Iterator[_VT]: ...
    def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ...
    def iterkeyrefs(self) -> Iterator[ref[_KT]]: ...
    def keyrefs(self) -> List[ref[_KT]]: ...
