-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathasfunction.py
More file actions
59 lines (44 loc) · 1.73 KB
/
asfunction.py
File metadata and controls
59 lines (44 loc) · 1.73 KB
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
53
54
55
56
57
58
59
from abc import abstractmethod
from collections.abc import Callable
from functools import wraps
from inspect import iscoroutinefunction
from types import MethodType
from typing import Any, Protocol, runtime_checkable
from injection._core.common.asynchronous import Caller
from injection._core.module import Module, mod
type AsFunctionWrappedType[**P, T] = type[AsFunctionCallable[P, T]]
@runtime_checkable
class AsFunctionCallable[**P, T](Protocol):
__slots__ = ()
@abstractmethod
def call(self, *args: P.args, **kwargs: P.kwargs) -> T:
raise NotImplementedError
def asfunction[**P, T](
wrapped: AsFunctionWrappedType[P, T] | None = None,
/,
*,
module: Module | None = None,
threadsafe: bool | None = None,
) -> Any:
module = module or mod()
def decorator(wp: AsFunctionWrappedType[P, T]) -> Callable[P, T]:
fake_method = MethodType(wp.call, NotImplemented)
factory: Caller[..., AsFunctionCallable[P, T]] = module.make_injected_function(
wp,
threadsafe=threadsafe,
).__inject_metadata__
wrapper: Callable[P, T]
if iscoroutinefunction(fake_method):
@wraps(fake_method)
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
self = await factory.acall()
return await self.call(*args, **kwargs) # type: ignore[misc]
else:
@wraps(fake_method)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
self = factory.call()
return self.call(*args, **kwargs)
wrapper.__name__ = wp.__name__
wrapper.__qualname__ = wp.__qualname__
return wrapper
return decorator(wrapped) if wrapped else decorator