import sys
from collections.abc import Callable
from typing import Any, Generic, TypeVar, final, overload
from typing_extensions import Self

if sys.version_info >= (3, 9):
    from types import GenericAlias

_C = TypeVar("_C", bound=Callable[..., Any])
_T = TypeVar("_T")

@final
class CallableProxyType(Generic[_C]):  # "weakcallableproxy"
    def __eq__(self, value: object, /) -> bool: ...
    def __getattr__(self, attr: str) -> Any: ...
    __call__: _C

@final
class ProxyType(Generic[_T]):  # "weakproxy"
    def __eq__(self, value: object, /) -> bool: ...
    def __getattr__(self, attr: str) -> Any: ...

class ReferenceType(Generic[_T]):
    __callback__: Callable[[Self], Any]
    def __new__(cls, o: _T, callback: Callable[[Self], Any] | None = ..., /) -> Self: ...
    def __init__(self, o: _T, callback: Callable[[Self], Any] | None = ..., /) -> None: ...
    def __call__(self) -> _T | None: ...
    def __eq__(self, value: object, /) -> bool: ...
    def __hash__(self) -> int: ...
    if sys.version_info >= (3, 9):
        def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...

ref = ReferenceType

def getweakrefcount(object: Any, /) -> int: ...
def getweakrefs(object: Any, /) -> list[Any]: ...

# Return CallableProxyType if object is callable, ProxyType otherwise
@overload
def proxy(object: _C, callback: Callable[[_C], Any] | None = None, /) -> CallableProxyType[_C]: ...
@overload
def proxy(object: _T, callback: Callable[[_T], Any] | None = None, /) -> Any: ...
