-
Notifications
You must be signed in to change notification settings - Fork 6
/
exam3.py
52 lines (35 loc) · 1.27 KB
/
exam3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from __future__ import annotations
from typing import Any, Callable, Literal, TypeVar, overload
from typing_extensions import Concatenate, ParamSpec, Self
T = TypeVar("T")
R = TypeVar("R")
P = ParamSpec("P")
@overload
def deco(fn: Callable[P, T]) -> Callable[[Callable[[T], R]], Callable[P, R]]: ...
@overload
def deco(
fn: Callable[P, T], is_method: Literal[True]
) -> Callable[[Callable[[Any, T], R]], Callable[Concatenate[Any, P], R]]: ...
def deco( # type: ignore
fn: Callable[P, T], is_method: bool = False
) -> Callable[[Callable[[T], R] | Callable[[Any, T], R]], Callable[P, R] | Callable[Concatenate[Any, P], R]]:
def wrapper(func: Callable[[T], R] | Callable[[Any, T], R]) -> Callable[P, R] | Callable[Concatenate[Any, P], R]:
def inner(*args: P.args, **kwargs: P.kwargs):
if is_method:
return func(args[0], fn(*args[1:], **kwargs)) # type: ignore
return func(fn(*args, **kwargs)) # type: ignore
return inner
return wrapper
class A:
def __init__(self, num: int):
self.num = num
class B:
def foo(self, num: int):
...
@deco(A, is_method=True)
def add(self, args: A) -> Self:
print(args.num)
return self
b = B()
b.foo(1)
print(b.add(1).add(2).add(3))