Skip to content

Instantly share code, notes, and snippets.

@smagch
Last active November 22, 2022 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smagch/c05219eaa05634e5ae0ac0b92281adec to your computer and use it in GitHub Desktop.
Save smagch/c05219eaa05634e5ae0ac0b92281adec to your computer and use it in GitHub Desktop.
python decorator that cast argument type
from typing import Any, Callable, TypeVar, Type, cast, Union, Protocol
from functools import singledispatchmethod
T = TypeVar("T", int, str)
def stricttype(
type_: Type[T],
) -> Callable[[Callable[[Any, Any], None]], Callable[[Any, T], None]]:
def inner(method: Callable[[Any, Any], None]) -> Callable[[Any, T], None]:
return method
return inner
T_contra = TypeVar("T_contra", contravariant=True)
class StrictDispatch(Protocol[T_contra]):
def __call__(self, arg: T_contra) -> None:
...
def register(self, cls: Any, method: Any = None) -> None:
...
def strictsingledispatchmethod(
type_: T_contra,
) -> Callable[[singledispatchmethod], StrictDispatch[T_contra]]:
def inner(
method: singledispatchmethod,
) -> StrictDispatch[T_contra]:
return cast(StrictDispatch[T_contra], method)
return inner
Event = Union[int, str]
class Foo:
@stricttype(type_=int)
def hoge(self, arg: Any) -> None:
print("hoge")
@stricttype(type_=str)
def foo(self, arg: Any) -> None:
print("foo")
@strictsingledispatchmethod(type_=Event)
@singledispatchmethod
def dispatch(self, arg: Any) -> None:
print("dispatch")
@dispatch.register
def _dispatch_int(self, arg: int) -> None:
print("dispatch int", arg)
@dispatch.register
def _dispatch_str(self, arg: str) -> None:
print("dispatch str", arg)
foo = Foo()
foo.hoge(100)
foo.dispatch(100)
foo.dispatch("100")
foo.dispatch("fooooobar")
foo.dispatch("100")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment