Skip to content

Commit ff34de7

Browse files
authored
rename: ✏️ @asfunction call method
1 parent e235bae commit ff34de7

3 files changed

Lines changed: 20 additions & 21 deletions

File tree

documentation/integrations/unlisted-framework.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ issues.
1010

1111
## If your framework inspects function signatures
1212

13-
If your framework inspects function signatures, things get a bit trickier. This is because you'll need to **perform
14-
dependency injection first, then call the function**, which isn't always compatible with how decorators work on regular
15-
functions.
13+
If your framework inspects function signatures, things get a bit trickier. This is because dependencies can't be present
14+
in function parameters.
1615

17-
To solve this, you can define a class with a `__call__` method (where dependencies are injected), and use the
18-
`asfunction` decorator to turn it into a function.
16+
To solve this, you can define a class with a `call` method (where dependencies are injected when the class is
17+
instantiated), and use the `asfunction` decorator to turn it into a function.
1918

20-
The resulting function will have the same signature as the `__call__` method, but without the `self` parameter.
19+
The resulting function will have the same signature as the `call` method, but without the `self` parameter.
2120

2221
Example:
2322

@@ -26,10 +25,10 @@ from typing import NamedTuple
2625
from injection import asfunction
2726

2827
@asfunction
29-
class do_something(NamedTuple):
28+
class DoSomething(NamedTuple):
3029
service: MyService
3130

32-
def __call__(self):
31+
def call(self):
3332
self.service.do_work()
3433
```
3534

injection/_core/asfunction.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22
from collections.abc import Callable
33
from functools import wraps
44
from inspect import iscoroutinefunction
5+
from types import MethodType
56
from typing import Any, Protocol, runtime_checkable
67

78
from injection._core.common.asynchronous import Caller
89
from injection._core.module import Module, mod
910

10-
type AsFunctionWrappedType[**P, T] = type[_Callable[P, T]]
11+
type AsFunctionWrappedType[**P, T] = type[AsFunctionCallable[P, T]]
1112

1213

1314
@runtime_checkable
14-
class _Callable[**P, T](Protocol):
15+
class AsFunctionCallable[**P, T](Protocol):
1516
__slots__ = ()
1617

1718
@abstractmethod
18-
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
19+
def call(self, *args: P.args, **kwargs: P.kwargs) -> T:
1920
raise NotImplementedError
2021

2122

@@ -29,28 +30,27 @@ def asfunction[**P, T](
2930
module = module or mod()
3031

3132
def decorator(wp: AsFunctionWrappedType[P, T]) -> Callable[P, T]:
32-
get_method = wp.__call__.__get__
33-
method = get_method(NotImplemented)
34-
factory: Caller[..., Callable[P, T]] = module.make_injected_function(
33+
fake_method = MethodType(wp.call, NotImplemented)
34+
factory: Caller[..., AsFunctionCallable[P, T]] = module.make_injected_function(
3535
wp,
3636
threadsafe=threadsafe,
3737
).__inject_metadata__
3838

3939
wrapper: Callable[P, T]
4040

41-
if iscoroutinefunction(method):
41+
if iscoroutinefunction(fake_method):
4242

43-
@wraps(method)
43+
@wraps(fake_method)
4444
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
4545
self = await factory.acall()
46-
return await get_method(self)(*args, **kwargs)
46+
return await self.call(*args, **kwargs) # type: ignore[misc]
4747

4848
else:
4949

50-
@wraps(method)
50+
@wraps(fake_method)
5151
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
5252
self = factory.call()
53-
return get_method(self)(*args, **kwargs)
53+
return self.call(*args, **kwargs)
5454

5555
wrapper.__name__ = wp.__name__
5656
wrapper.__qualname__ = wp.__qualname__

tests/core/test_asfunction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Dependency: ...
1212
class SyncFunction(NamedTuple):
1313
dependency: Dependency
1414

15-
def __call__(self):
15+
def call(self):
1616
return self.dependency
1717

1818
assert isinstance(SyncFunction(), Dependency)
@@ -28,7 +28,7 @@ async def dependency_recipe() -> Dependency:
2828
class AsyncFunction(NamedTuple):
2929
dependency: Dependency
3030

31-
async def __call__(self):
31+
async def call(self):
3232
return self.dependency
3333

3434
assert isinstance(await AsyncFunction(), Dependency)

0 commit comments

Comments
 (0)