%PDF- %PDF-
Direktori : /backups/router/usr/local/lib/python3.11/site-packages/socksio/ |
Current File : //backups/router/usr/local/lib/python3.11/site-packages/socksio/compat.py |
"""Backport of @functools.singledispatchmethod to Python <3.7. Adapted from https://github.com/ikalnytskyi/singledispatchmethod removing 2.7 specific code. """ import functools import typing if hasattr(functools, "singledispatchmethod"): # pragma: nocover singledispatchmethod = functools.singledispatchmethod # type: ignore else: update_wrapper = functools.update_wrapper singledispatch = functools.singledispatch # The type: ignore below is to avoid mypy erroring due to a # "already defined" singledispatchmethod, oddly this does not # happen when using `if sys.version_info >= (3, 8)` class singledispatchmethod(object): # type: ignore """Single-dispatch generic method descriptor. TODO: Figure out how to type this: `mypy --strict` returns errors like the following for all decorated methods: "Untyped decorator makes function "send" untyped." But this is not a normal function-base decorator, it's a class and it doesn't have a __call__ method. When decorating the "base" method __init__ is called, but of course its return type is None. """ def __init__(self, func: typing.Callable[..., typing.Any]) -> None: if not callable(func) and not hasattr(func, "__get__"): raise TypeError("{!r} is not callable or a descriptor".format(func)) self.dispatcher = singledispatch(func) self.func = func def register( self, cls: typing.Callable[..., typing.Any], method: typing.Optional[typing.Callable[..., typing.Any]] = None, ) -> typing.Callable[..., typing.Any]: """Register a method on a class for a particular type. Note in Python <= 3.6 this methods cannot infer the type from the argument's type annotation, users *must* supply it manually on decoration, i.e. @my_method.register(TypeToDispatch) def _(self, arg: TypeToDispatch) -> None: ... Versus in Python 3.7+: @my_method.register def _(self, arg: TypeToDispatch) -> None: ... """ # mypy wants method to be non-optional, but it is required to be # for decoration to work correctly in our case. # https://github.com/python/cpython/blob/3.8/Lib/functools.py#L887-L920 # is not type annotated either. return self.dispatcher.register(cls, func=method) # type: ignore def __get__( self, obj: typing.Any, cls: typing.Callable[[typing.Any], typing.Any] ) -> typing.Callable[..., typing.Any]: def _method(*args: typing.Any, **kwargs: typing.Any) -> typing.Any: method = self.dispatcher.dispatch(args[0].__class__) # type: typing.Any return method.__get__(obj, cls)(*args, **kwargs) # The type: ignore below is due to `_method` being given a strict # "Callable[[VarArg(Any), KwArg(Any)], Any]" which causes a # 'has no attribute "__isabstractmethod__" error' # felt safe enough to ignore _method.__isabstractmethod__ = self.__isabstractmethod__ # type: ignore _method.register = self.register # type: ignore update_wrapper(_method, self.func) return _method @property def __isabstractmethod__(self) -> typing.Any: return getattr(self.func, "__isabstractmethod__", False)