56 lines
1.3 KiB
Python
56 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import (
|
|
Any,
|
|
Callable,
|
|
Generic,
|
|
Optional,
|
|
Type,
|
|
TypeVar,
|
|
)
|
|
|
|
from typing_extensions import (
|
|
Concatenate,
|
|
ParamSpec,
|
|
Self,
|
|
)
|
|
|
|
|
|
SelfT = TypeVar("SelfT")
|
|
P = ParamSpec("P")
|
|
HybridT = TypeVar("HybridT", covariant=True)
|
|
|
|
|
|
class hybridmethod(Generic[SelfT, P, HybridT]):
|
|
def __init__(
|
|
self,
|
|
func: Callable[
|
|
Concatenate[type[SelfT], P], HybridT
|
|
], # Must be the classmethod version
|
|
):
|
|
self.cls_func = func
|
|
self.__doc__ = func.__doc__
|
|
|
|
def instancemethod(self, func: Callable[Concatenate[SelfT, P], HybridT]) -> Self:
|
|
self.instance_func = func
|
|
return self
|
|
|
|
def __get__(
|
|
self, instance: Optional[SelfT], owner: Type[SelfT]
|
|
) -> Callable[P, HybridT]:
|
|
if instance is None or self.instance_func is None:
|
|
# either bound to the class, or no instance method available
|
|
return self.cls_func.__get__(owner, None)
|
|
return self.instance_func.__get__(instance, owner)
|
|
|
|
|
|
T_co = TypeVar("T_co")
|
|
TT_co = TypeVar("TT_co", bound="type[Any]")
|
|
|
|
|
|
class classproperty(Generic[TT_co, T_co]):
|
|
def __init__(self, func: Callable[[TT_co], T_co]):
|
|
self.__func__ = func
|
|
|
|
def __get__(self, instance: Any, type: TT_co) -> T_co:
|
|
return self.__func__(type)
|