python-injection 0.18.14__py3-none-any.whl → 0.19.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- injection/__init__.py +2 -0
- injection/__init__.pyi +39 -17
- injection/_core/asfunction.py +59 -0
- injection/_core/common/asynchronous.py +20 -14
- injection/_core/common/threading.py +1 -1
- injection/_core/descriptors.py +1 -1
- injection/_core/injectables.py +2 -5
- injection/_core/module.py +30 -20
- injection/_core/scope.py +3 -3
- injection/entrypoint.py +16 -16
- injection/ext/fastapi.py +5 -5
- {python_injection-0.18.14.dist-info → python_injection-0.19.1.dist-info}/METADATA +2 -1
- python_injection-0.19.1.dist-info/RECORD +30 -0
- python_injection-0.18.14.dist-info/RECORD +0 -29
- {python_injection-0.18.14.dist-info → python_injection-0.19.1.dist-info}/WHEEL +0 -0
- {python_injection-0.18.14.dist-info → python_injection-0.19.1.dist-info}/licenses/LICENSE +0 -0
injection/__init__.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from ._core.asfunction import asfunction
|
1
2
|
from ._core.descriptors import LazyInstance
|
2
3
|
from ._core.injectables import Injectable
|
3
4
|
from ._core.module import Mode, Module, Priority, mod
|
@@ -18,6 +19,7 @@ __all__ = (
|
|
18
19
|
"afind_instance",
|
19
20
|
"aget_instance",
|
20
21
|
"aget_lazy_instance",
|
22
|
+
"asfunction",
|
21
23
|
"constant",
|
22
24
|
"define_scope",
|
23
25
|
"find_instance",
|
injection/__init__.pyi
CHANGED
@@ -5,6 +5,7 @@ from enum import Enum
|
|
5
5
|
from logging import Logger
|
6
6
|
from typing import Any, Final, Protocol, Self, final, overload, runtime_checkable
|
7
7
|
|
8
|
+
from ._core.asfunction import AsFunctionWrappedType as _AsFunctionWrappedType
|
8
9
|
from ._core.common.invertible import Invertible as _Invertible
|
9
10
|
from ._core.common.type import InputType as _InputType
|
10
11
|
from ._core.common.type import TypeInfo as _TypeInfo
|
@@ -30,19 +31,35 @@ set_constant = __MODULE.set_constant
|
|
30
31
|
should_be_injectable = __MODULE.should_be_injectable
|
31
32
|
singleton = __MODULE.singleton
|
32
33
|
|
34
|
+
@overload
|
35
|
+
def asfunction[**P, T](
|
36
|
+
wrapped: _AsFunctionWrappedType[P, T],
|
37
|
+
/,
|
38
|
+
*,
|
39
|
+
module: Module = ...,
|
40
|
+
threadsafe: bool | None = ...,
|
41
|
+
) -> Callable[P, T]: ...
|
42
|
+
@overload
|
43
|
+
def asfunction[**P, T](
|
44
|
+
wrapped: None = ...,
|
45
|
+
/,
|
46
|
+
*,
|
47
|
+
module: Module = ...,
|
48
|
+
threadsafe: bool | None = ...,
|
49
|
+
) -> Callable[[_AsFunctionWrappedType[P, T]], Callable[P, T]]: ...
|
33
50
|
@asynccontextmanager
|
34
51
|
def adefine_scope(
|
35
52
|
name: str,
|
36
53
|
/,
|
37
54
|
kind: ScopeKind | ScopeKindStr = ...,
|
38
|
-
threadsafe: bool = ...,
|
55
|
+
threadsafe: bool | None = ...,
|
39
56
|
) -> AsyncIterator[Scope]: ...
|
40
57
|
@contextmanager
|
41
58
|
def define_scope(
|
42
59
|
name: str,
|
43
60
|
/,
|
44
61
|
kind: ScopeKind | ScopeKindStr = ...,
|
45
|
-
threadsafe: bool = ...,
|
62
|
+
threadsafe: bool | None = ...,
|
46
63
|
) -> Iterator[Scope]: ...
|
47
64
|
def mod(name: str = ..., /) -> Module:
|
48
65
|
"""
|
@@ -80,7 +97,7 @@ class LazyInstance[T]:
|
|
80
97
|
default: T = ...,
|
81
98
|
*,
|
82
99
|
module: Module = ...,
|
83
|
-
threadsafe: bool = ...,
|
100
|
+
threadsafe: bool | None = ...,
|
84
101
|
) -> None: ...
|
85
102
|
@overload
|
86
103
|
def __get__(self, instance: object, owner: type | None = ...) -> T: ...
|
@@ -108,7 +125,7 @@ class Module:
|
|
108
125
|
wrapped: Callable[P, T] = ...,
|
109
126
|
/,
|
110
127
|
*,
|
111
|
-
threadsafe: bool = ...,
|
128
|
+
threadsafe: bool | None = ...,
|
112
129
|
) -> Any:
|
113
130
|
"""
|
114
131
|
Decorator applicable to a class or function. Inject function dependencies using
|
@@ -149,7 +166,7 @@ class Module:
|
|
149
166
|
always be the same.
|
150
167
|
"""
|
151
168
|
|
152
|
-
def scoped[
|
169
|
+
def scoped[T](
|
153
170
|
self,
|
154
171
|
scope_name: str,
|
155
172
|
/,
|
@@ -211,21 +228,26 @@ class Module:
|
|
211
228
|
self,
|
212
229
|
wrapped: Callable[P, T],
|
213
230
|
/,
|
214
|
-
threadsafe: bool = ...,
|
231
|
+
threadsafe: bool | None = ...,
|
215
232
|
) -> Callable[P, T]: ...
|
216
233
|
def make_async_factory[T](
|
217
234
|
self,
|
218
235
|
wrapped: type[T],
|
219
236
|
/,
|
220
|
-
threadsafe: bool = ...,
|
237
|
+
threadsafe: bool | None = ...,
|
221
238
|
) -> Callable[..., Awaitable[T]]: ...
|
222
239
|
async def afind_instance[T](
|
223
240
|
self,
|
224
241
|
cls: _InputType[T],
|
225
242
|
*,
|
226
|
-
threadsafe: bool = ...,
|
243
|
+
threadsafe: bool | None = ...,
|
227
244
|
) -> T: ...
|
228
|
-
def find_instance[T](
|
245
|
+
def find_instance[T](
|
246
|
+
self,
|
247
|
+
cls: _InputType[T],
|
248
|
+
*,
|
249
|
+
threadsafe: bool | None = ...,
|
250
|
+
) -> T:
|
229
251
|
"""
|
230
252
|
Function used to retrieve an instance associated with the type passed in
|
231
253
|
parameter or an exception will be raised.
|
@@ -237,7 +259,7 @@ class Module:
|
|
237
259
|
cls: _InputType[T],
|
238
260
|
default: Default,
|
239
261
|
*,
|
240
|
-
threadsafe: bool = ...,
|
262
|
+
threadsafe: bool | None = ...,
|
241
263
|
) -> T | Default: ...
|
242
264
|
@overload
|
243
265
|
async def aget_instance[T](
|
@@ -245,7 +267,7 @@ class Module:
|
|
245
267
|
cls: _InputType[T],
|
246
268
|
default: T = ...,
|
247
269
|
*,
|
248
|
-
threadsafe: bool = ...,
|
270
|
+
threadsafe: bool | None = ...,
|
249
271
|
) -> T: ...
|
250
272
|
@overload
|
251
273
|
def get_instance[T, Default](
|
@@ -253,7 +275,7 @@ class Module:
|
|
253
275
|
cls: _InputType[T],
|
254
276
|
default: Default,
|
255
277
|
*,
|
256
|
-
threadsafe: bool = ...,
|
278
|
+
threadsafe: bool | None = ...,
|
257
279
|
) -> T | Default:
|
258
280
|
"""
|
259
281
|
Function used to retrieve an instance associated with the type passed in
|
@@ -266,7 +288,7 @@ class Module:
|
|
266
288
|
cls: _InputType[T],
|
267
289
|
default: T = ...,
|
268
290
|
*,
|
269
|
-
threadsafe: bool = ...,
|
291
|
+
threadsafe: bool | None = ...,
|
270
292
|
) -> T: ...
|
271
293
|
@overload
|
272
294
|
def aget_lazy_instance[T, Default](
|
@@ -274,7 +296,7 @@ class Module:
|
|
274
296
|
cls: _InputType[T],
|
275
297
|
default: Default,
|
276
298
|
*,
|
277
|
-
threadsafe: bool = ...,
|
299
|
+
threadsafe: bool | None = ...,
|
278
300
|
) -> Awaitable[T | Default]: ...
|
279
301
|
@overload
|
280
302
|
def aget_lazy_instance[T](
|
@@ -282,7 +304,7 @@ class Module:
|
|
282
304
|
cls: _InputType[T],
|
283
305
|
default: T = ...,
|
284
306
|
*,
|
285
|
-
threadsafe: bool = ...,
|
307
|
+
threadsafe: bool | None = ...,
|
286
308
|
) -> Awaitable[T]: ...
|
287
309
|
@overload
|
288
310
|
def get_lazy_instance[T, Default](
|
@@ -290,7 +312,7 @@ class Module:
|
|
290
312
|
cls: _InputType[T],
|
291
313
|
default: Default,
|
292
314
|
*,
|
293
|
-
threadsafe: bool = ...,
|
315
|
+
threadsafe: bool | None = ...,
|
294
316
|
) -> _Invertible[T | Default]:
|
295
317
|
"""
|
296
318
|
Function used to retrieve an instance associated with the type passed in
|
@@ -306,7 +328,7 @@ class Module:
|
|
306
328
|
cls: _InputType[T],
|
307
329
|
default: T = ...,
|
308
330
|
*,
|
309
|
-
threadsafe: bool = ...,
|
331
|
+
threadsafe: bool | None = ...,
|
310
332
|
) -> _Invertible[T]: ...
|
311
333
|
def init_modules(self, *modules: Module) -> Self:
|
312
334
|
"""
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from abc import abstractmethod
|
2
|
+
from collections.abc import Callable
|
3
|
+
from functools import wraps
|
4
|
+
from inspect import iscoroutinefunction
|
5
|
+
from typing import Any, Protocol, runtime_checkable
|
6
|
+
|
7
|
+
from injection._core.common.asynchronous import Caller
|
8
|
+
from injection._core.module import Module, mod
|
9
|
+
|
10
|
+
type AsFunctionWrappedType[**P, T] = type[_Callable[P, T]]
|
11
|
+
|
12
|
+
|
13
|
+
@runtime_checkable
|
14
|
+
class _Callable[**P, T](Protocol):
|
15
|
+
__slots__ = ()
|
16
|
+
|
17
|
+
@abstractmethod
|
18
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
|
19
|
+
raise NotImplementedError
|
20
|
+
|
21
|
+
|
22
|
+
def asfunction[**P, T](
|
23
|
+
wrapped: AsFunctionWrappedType[P, T] | None = None,
|
24
|
+
/,
|
25
|
+
*,
|
26
|
+
module: Module | None = None,
|
27
|
+
threadsafe: bool | None = None,
|
28
|
+
) -> Any:
|
29
|
+
module = module or mod()
|
30
|
+
|
31
|
+
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(
|
35
|
+
wp,
|
36
|
+
threadsafe=threadsafe,
|
37
|
+
).__inject_metadata__
|
38
|
+
|
39
|
+
wrapper: Callable[P, T]
|
40
|
+
|
41
|
+
if iscoroutinefunction(method):
|
42
|
+
|
43
|
+
@wraps(method)
|
44
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
|
45
|
+
self = await factory.acall()
|
46
|
+
return await get_method(self)(*args, **kwargs)
|
47
|
+
|
48
|
+
else:
|
49
|
+
|
50
|
+
@wraps(method)
|
51
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
52
|
+
self = factory.call()
|
53
|
+
return get_method(self)(*args, **kwargs)
|
54
|
+
|
55
|
+
wrapper.__name__ = wp.__name__
|
56
|
+
wrapper.__qualname__ = wp.__qualname__
|
57
|
+
return wrapper
|
58
|
+
|
59
|
+
return decorator(wrapped) if wrapped else decorator
|
@@ -1,7 +1,26 @@
|
|
1
1
|
from abc import abstractmethod
|
2
2
|
from collections.abc import Awaitable, Callable, Generator
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
4
|
+
from typing import (
|
5
|
+
Any,
|
6
|
+
AsyncContextManager,
|
7
|
+
NoReturn,
|
8
|
+
Protocol,
|
9
|
+
runtime_checkable,
|
10
|
+
)
|
11
|
+
|
12
|
+
AsyncSemaphore: Callable[[int], AsyncContextManager[Any]]
|
13
|
+
|
14
|
+
try:
|
15
|
+
import anyio
|
16
|
+
|
17
|
+
except ImportError: # pragma: no cover
|
18
|
+
import asyncio
|
19
|
+
|
20
|
+
AsyncSemaphore = asyncio.Semaphore
|
21
|
+
|
22
|
+
else:
|
23
|
+
AsyncSemaphore = anyio.Semaphore
|
5
24
|
|
6
25
|
|
7
26
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
@@ -45,16 +64,3 @@ class SyncCaller[**P, T](Caller[P, T]):
|
|
45
64
|
|
46
65
|
def call(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
47
66
|
return self.callable(*args, **kwargs)
|
48
|
-
|
49
|
-
|
50
|
-
try:
|
51
|
-
import anyio
|
52
|
-
|
53
|
-
def create_semaphore(value: int) -> AsyncContextManager[Any]:
|
54
|
-
return anyio.Semaphore(value)
|
55
|
-
|
56
|
-
except ImportError: # pragma: no cover
|
57
|
-
import asyncio
|
58
|
-
|
59
|
-
def create_semaphore(value: int) -> AsyncContextManager[Any]:
|
60
|
-
return asyncio.Semaphore(value)
|
injection/_core/descriptors.py
CHANGED
@@ -17,7 +17,7 @@ class LazyInstance[T]:
|
|
17
17
|
default: T = NotImplemented,
|
18
18
|
*,
|
19
19
|
module: Module | None = None,
|
20
|
-
threadsafe: bool =
|
20
|
+
threadsafe: bool | None = None,
|
21
21
|
) -> None:
|
22
22
|
module = module or mod()
|
23
23
|
self.__value = module.get_lazy_instance(cls, default, threadsafe=threadsafe)
|
injection/_core/injectables.py
CHANGED
@@ -13,10 +13,7 @@ from typing import (
|
|
13
13
|
runtime_checkable,
|
14
14
|
)
|
15
15
|
|
16
|
-
from injection._core.common.asynchronous import Caller
|
17
|
-
from injection._core.common.asynchronous import (
|
18
|
-
create_semaphore as _create_async_semaphore,
|
19
|
-
)
|
16
|
+
from injection._core.common.asynchronous import AsyncSemaphore, Caller
|
20
17
|
from injection._core.scope import (
|
21
18
|
Scope,
|
22
19
|
get_scope,
|
@@ -64,7 +61,7 @@ class CacheLogic[T]:
|
|
64
61
|
__semaphore: AsyncContextManager[Any]
|
65
62
|
|
66
63
|
def __init__(self) -> None:
|
67
|
-
self.__semaphore =
|
64
|
+
self.__semaphore = AsyncSemaphore(1)
|
68
65
|
|
69
66
|
async def aget_or_create[K](
|
70
67
|
self,
|
injection/_core/module.py
CHANGED
@@ -560,7 +560,7 @@ class Module(Broker, EventListener):
|
|
560
560
|
wrapped: Callable[P, T] | None = None,
|
561
561
|
/,
|
562
562
|
*,
|
563
|
-
threadsafe: bool =
|
563
|
+
threadsafe: bool | None = None,
|
564
564
|
) -> Any:
|
565
565
|
def decorator(wp: Callable[P, T]) -> Callable[P, T]:
|
566
566
|
if isclass(wp):
|
@@ -576,7 +576,7 @@ class Module(Broker, EventListener):
|
|
576
576
|
self,
|
577
577
|
wrapped: Callable[P, T],
|
578
578
|
/,
|
579
|
-
threadsafe: bool = ...,
|
579
|
+
threadsafe: bool | None = ...,
|
580
580
|
) -> SyncInjectedFunction[P, T]: ...
|
581
581
|
|
582
582
|
@overload
|
@@ -584,14 +584,14 @@ class Module(Broker, EventListener):
|
|
584
584
|
self,
|
585
585
|
wrapped: Callable[P, Awaitable[T]],
|
586
586
|
/,
|
587
|
-
threadsafe: bool = ...,
|
587
|
+
threadsafe: bool | None = ...,
|
588
588
|
) -> AsyncInjectedFunction[P, T]: ...
|
589
589
|
|
590
590
|
def make_injected_function[**P, T](
|
591
591
|
self,
|
592
592
|
wrapped: Callable[P, T],
|
593
593
|
/,
|
594
|
-
threadsafe: bool =
|
594
|
+
threadsafe: bool | None = None,
|
595
595
|
) -> InjectedFunction[P, T]:
|
596
596
|
metadata = InjectMetadata(wrapped, threadsafe)
|
597
597
|
|
@@ -609,7 +609,7 @@ class Module(Broker, EventListener):
|
|
609
609
|
self,
|
610
610
|
wrapped: type[T],
|
611
611
|
/,
|
612
|
-
threadsafe: bool =
|
612
|
+
threadsafe: bool | None = None,
|
613
613
|
) -> Callable[..., Awaitable[T]]:
|
614
614
|
factory: InjectedFunction[..., T] = self.make_injected_function(
|
615
615
|
wrapped,
|
@@ -621,13 +621,18 @@ class Module(Broker, EventListener):
|
|
621
621
|
self,
|
622
622
|
cls: InputType[T],
|
623
623
|
*,
|
624
|
-
threadsafe: bool =
|
624
|
+
threadsafe: bool | None = None,
|
625
625
|
) -> T:
|
626
626
|
with get_lock(threadsafe):
|
627
627
|
injectable = self[cls]
|
628
628
|
return await injectable.aget_instance()
|
629
629
|
|
630
|
-
def find_instance[T](
|
630
|
+
def find_instance[T](
|
631
|
+
self,
|
632
|
+
cls: InputType[T],
|
633
|
+
*,
|
634
|
+
threadsafe: bool | None = None,
|
635
|
+
) -> T:
|
631
636
|
with get_lock(threadsafe):
|
632
637
|
injectable = self[cls]
|
633
638
|
return injectable.get_instance()
|
@@ -638,7 +643,7 @@ class Module(Broker, EventListener):
|
|
638
643
|
cls: InputType[T],
|
639
644
|
default: Default,
|
640
645
|
*,
|
641
|
-
threadsafe: bool = ...,
|
646
|
+
threadsafe: bool | None = ...,
|
642
647
|
) -> T | Default: ...
|
643
648
|
|
644
649
|
@overload
|
@@ -647,7 +652,7 @@ class Module(Broker, EventListener):
|
|
647
652
|
cls: InputType[T],
|
648
653
|
default: T = ...,
|
649
654
|
*,
|
650
|
-
threadsafe: bool = ...,
|
655
|
+
threadsafe: bool | None = ...,
|
651
656
|
) -> T: ...
|
652
657
|
|
653
658
|
async def aget_instance[T, Default](
|
@@ -655,7 +660,7 @@ class Module(Broker, EventListener):
|
|
655
660
|
cls: InputType[T],
|
656
661
|
default: Default = NotImplemented,
|
657
662
|
*,
|
658
|
-
threadsafe: bool =
|
663
|
+
threadsafe: bool | None = None,
|
659
664
|
) -> T | Default:
|
660
665
|
try:
|
661
666
|
return await self.afind_instance(cls, threadsafe=threadsafe)
|
@@ -668,7 +673,7 @@ class Module(Broker, EventListener):
|
|
668
673
|
cls: InputType[T],
|
669
674
|
default: Default,
|
670
675
|
*,
|
671
|
-
threadsafe: bool = ...,
|
676
|
+
threadsafe: bool | None = ...,
|
672
677
|
) -> T | Default: ...
|
673
678
|
|
674
679
|
@overload
|
@@ -677,7 +682,7 @@ class Module(Broker, EventListener):
|
|
677
682
|
cls: InputType[T],
|
678
683
|
default: T = ...,
|
679
684
|
*,
|
680
|
-
threadsafe: bool = ...,
|
685
|
+
threadsafe: bool | None = ...,
|
681
686
|
) -> T: ...
|
682
687
|
|
683
688
|
def get_instance[T, Default](
|
@@ -685,7 +690,7 @@ class Module(Broker, EventListener):
|
|
685
690
|
cls: InputType[T],
|
686
691
|
default: Default = NotImplemented,
|
687
692
|
*,
|
688
|
-
threadsafe: bool =
|
693
|
+
threadsafe: bool | None = None,
|
689
694
|
) -> T | Default:
|
690
695
|
try:
|
691
696
|
return self.find_instance(cls, threadsafe=threadsafe)
|
@@ -698,7 +703,7 @@ class Module(Broker, EventListener):
|
|
698
703
|
cls: InputType[T],
|
699
704
|
default: Default,
|
700
705
|
*,
|
701
|
-
threadsafe: bool = ...,
|
706
|
+
threadsafe: bool | None = ...,
|
702
707
|
) -> Awaitable[T | Default]: ...
|
703
708
|
|
704
709
|
@overload
|
@@ -707,7 +712,7 @@ class Module(Broker, EventListener):
|
|
707
712
|
cls: InputType[T],
|
708
713
|
default: T = ...,
|
709
714
|
*,
|
710
|
-
threadsafe: bool = ...,
|
715
|
+
threadsafe: bool | None = ...,
|
711
716
|
) -> Awaitable[T]: ...
|
712
717
|
|
713
718
|
def aget_lazy_instance[T, Default](
|
@@ -715,7 +720,7 @@ class Module(Broker, EventListener):
|
|
715
720
|
cls: InputType[T],
|
716
721
|
default: Default = NotImplemented,
|
717
722
|
*,
|
718
|
-
threadsafe: bool =
|
723
|
+
threadsafe: bool | None = None,
|
719
724
|
) -> Awaitable[T | Default]:
|
720
725
|
function = self.make_injected_function(
|
721
726
|
lambda instance=default: instance,
|
@@ -730,7 +735,7 @@ class Module(Broker, EventListener):
|
|
730
735
|
cls: InputType[T],
|
731
736
|
default: Default,
|
732
737
|
*,
|
733
|
-
threadsafe: bool = ...,
|
738
|
+
threadsafe: bool | None = ...,
|
734
739
|
) -> Invertible[T | Default]: ...
|
735
740
|
|
736
741
|
@overload
|
@@ -739,7 +744,7 @@ class Module(Broker, EventListener):
|
|
739
744
|
cls: InputType[T],
|
740
745
|
default: T = ...,
|
741
746
|
*,
|
742
|
-
threadsafe: bool = ...,
|
747
|
+
threadsafe: bool | None = ...,
|
743
748
|
) -> Invertible[T]: ...
|
744
749
|
|
745
750
|
def get_lazy_instance[T, Default](
|
@@ -747,7 +752,7 @@ class Module(Broker, EventListener):
|
|
747
752
|
cls: InputType[T],
|
748
753
|
default: Default = NotImplemented,
|
749
754
|
*,
|
750
|
-
threadsafe: bool =
|
755
|
+
threadsafe: bool | None = None,
|
751
756
|
) -> Invertible[T | Default]:
|
752
757
|
function = self.make_injected_function(
|
753
758
|
lambda instance=default: instance,
|
@@ -1013,7 +1018,12 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
|
|
1013
1018
|
__tasks: deque[Callable[..., Any]]
|
1014
1019
|
__wrapped: Callable[P, T]
|
1015
1020
|
|
1016
|
-
def __init__(
|
1021
|
+
def __init__(
|
1022
|
+
self,
|
1023
|
+
wrapped: Callable[P, T],
|
1024
|
+
/,
|
1025
|
+
threadsafe: bool | None = None,
|
1026
|
+
) -> None:
|
1017
1027
|
self.__dependencies = Dependencies.empty()
|
1018
1028
|
self.__lock = get_lock(threadsafe)
|
1019
1029
|
self.__owner = None
|
injection/_core/scope.py
CHANGED
@@ -130,7 +130,7 @@ async def adefine_scope(
|
|
130
130
|
name: str,
|
131
131
|
/,
|
132
132
|
kind: ScopeKind | ScopeKindStr = ScopeKind.get_default(),
|
133
|
-
threadsafe: bool =
|
133
|
+
threadsafe: bool | None = None,
|
134
134
|
) -> AsyncIterator[ScopeFacade]:
|
135
135
|
async with AsyncScope() as scope:
|
136
136
|
with _bind_scope(name, scope, kind, threadsafe) as facade:
|
@@ -142,7 +142,7 @@ def define_scope(
|
|
142
142
|
name: str,
|
143
143
|
/,
|
144
144
|
kind: ScopeKind | ScopeKindStr = ScopeKind.get_default(),
|
145
|
-
threadsafe: bool =
|
145
|
+
threadsafe: bool | None = None,
|
146
146
|
) -> Iterator[ScopeFacade]:
|
147
147
|
with SyncScope() as scope:
|
148
148
|
with _bind_scope(name, scope, kind, threadsafe) as facade:
|
@@ -194,7 +194,7 @@ def _bind_scope(
|
|
194
194
|
name: str,
|
195
195
|
scope: Scope,
|
196
196
|
kind: ScopeKind | ScopeKindStr,
|
197
|
-
threadsafe: bool,
|
197
|
+
threadsafe: bool | None,
|
198
198
|
) -> Iterator[ScopeFacade]:
|
199
199
|
lock = get_lock(threadsafe)
|
200
200
|
|
injection/entrypoint.py
CHANGED
@@ -7,7 +7,7 @@ from dataclasses import dataclass, field
|
|
7
7
|
from functools import wraps
|
8
8
|
from types import MethodType
|
9
9
|
from types import ModuleType as PythonModule
|
10
|
-
from typing import Any, Self, final, overload
|
10
|
+
from typing import Any, Concatenate, Self, final, overload
|
11
11
|
|
12
12
|
from injection import Module
|
13
13
|
from injection.loaders import ProfileLoader, PythonModuleLoader
|
@@ -16,9 +16,9 @@ __all__ = ("AsyncEntrypoint", "Entrypoint", "autocall", "entrypointmaker")
|
|
16
16
|
|
17
17
|
type AsyncEntrypoint[**P, T] = Entrypoint[P, Coroutine[Any, Any, T]]
|
18
18
|
type EntrypointDecorator[**P, T1, T2] = Callable[[Callable[P, T1]], Callable[P, T2]]
|
19
|
-
type EntrypointSetupMethod[
|
20
|
-
[Entrypoint[
|
21
|
-
Entrypoint[
|
19
|
+
type EntrypointSetupMethod[**P, **EPP, T1, T2] = Callable[
|
20
|
+
Concatenate[Entrypoint[EPP, T1], P],
|
21
|
+
Entrypoint[EPP, T2],
|
22
22
|
]
|
23
23
|
|
24
24
|
|
@@ -31,35 +31,35 @@ def autocall[**P, T](wrapped: Callable[P, T] | None = None, /) -> Any:
|
|
31
31
|
|
32
32
|
|
33
33
|
@overload
|
34
|
-
def entrypointmaker[
|
35
|
-
wrapped: EntrypointSetupMethod[
|
34
|
+
def entrypointmaker[**SMP, **EPP, T1, T2](
|
35
|
+
wrapped: EntrypointSetupMethod[SMP, EPP, T1, T2],
|
36
36
|
/,
|
37
37
|
*,
|
38
38
|
profile_loader: ProfileLoader = ...,
|
39
|
-
) -> EntrypointDecorator[
|
39
|
+
) -> EntrypointDecorator[EPP, T1, T2]: ...
|
40
40
|
|
41
41
|
|
42
42
|
@overload
|
43
|
-
def entrypointmaker[
|
43
|
+
def entrypointmaker[**SMP, **EPP, T1, T2](
|
44
44
|
wrapped: None = ...,
|
45
45
|
/,
|
46
46
|
*,
|
47
47
|
profile_loader: ProfileLoader = ...,
|
48
48
|
) -> Callable[
|
49
|
-
[EntrypointSetupMethod[
|
50
|
-
EntrypointDecorator[
|
49
|
+
[EntrypointSetupMethod[SMP, EPP, T1, T2]],
|
50
|
+
EntrypointDecorator[EPP, T1, T2],
|
51
51
|
]: ...
|
52
52
|
|
53
53
|
|
54
|
-
def entrypointmaker[
|
55
|
-
wrapped: EntrypointSetupMethod[
|
54
|
+
def entrypointmaker[**SMP, **EPP, T1, T2](
|
55
|
+
wrapped: EntrypointSetupMethod[SMP, EPP, T1, T2] | None = None,
|
56
56
|
/,
|
57
57
|
*,
|
58
58
|
profile_loader: ProfileLoader | None = None,
|
59
59
|
) -> Any:
|
60
60
|
def decorator(
|
61
|
-
wp: EntrypointSetupMethod[
|
62
|
-
) -> EntrypointDecorator[
|
61
|
+
wp: EntrypointSetupMethod[SMP, EPP, T1, T2],
|
62
|
+
) -> EntrypointDecorator[EPP, T1, T2]:
|
63
63
|
return Entrypoint._make_decorator(wp, profile_loader)
|
64
64
|
|
65
65
|
return decorator(wrapped) if wrapped else decorator
|
@@ -143,9 +143,9 @@ class Entrypoint[**P, T]:
|
|
143
143
|
return type(self)(function, self.profile_loader)
|
144
144
|
|
145
145
|
@classmethod
|
146
|
-
def _make_decorator[
|
146
|
+
def _make_decorator[**_P, _T](
|
147
147
|
cls,
|
148
|
-
setup_method: EntrypointSetupMethod[
|
148
|
+
setup_method: EntrypointSetupMethod[_P, P, T, _T],
|
149
149
|
/,
|
150
150
|
profile_loader: ProfileLoader | None = None,
|
151
151
|
) -> EntrypointDecorator[P, T, _T]:
|
injection/ext/fastapi.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from dataclasses import dataclass, field
|
2
2
|
from types import GenericAlias
|
3
|
-
from typing import Annotated, Any, TypeAliasType
|
3
|
+
from typing import Annotated, Any, TypeAlias, TypeAliasType
|
4
4
|
|
5
5
|
from fastapi import Depends
|
6
6
|
|
@@ -12,7 +12,7 @@ __all__ = ("Inject", "InjectThreadSafe")
|
|
12
12
|
@dataclass(eq=False, frozen=True, slots=True)
|
13
13
|
class FastAPIInject:
|
14
14
|
module: Module = field(default_factory=mod)
|
15
|
-
threadsafe: bool = field(default=
|
15
|
+
threadsafe: bool | None = field(default=None, kw_only=True)
|
16
16
|
|
17
17
|
def __call__[T](
|
18
18
|
self,
|
@@ -25,16 +25,16 @@ class FastAPIInject:
|
|
25
25
|
) -> Any:
|
26
26
|
module = module or self.module
|
27
27
|
threadsafe = self.threadsafe if threadsafe is None else threadsafe
|
28
|
-
|
28
|
+
lazy_instance = module.aget_lazy_instance(cls, default, threadsafe=threadsafe)
|
29
29
|
|
30
30
|
async def dependency() -> T:
|
31
|
-
return await
|
31
|
+
return await lazy_instance
|
32
32
|
|
33
33
|
class_name = getattr(cls, "__name__", str(cls))
|
34
34
|
dependency.__name__ = f"inject({class_name})"
|
35
35
|
return Depends(dependency, use_cache=False)
|
36
36
|
|
37
|
-
def __getitem__(self, params:
|
37
|
+
def __getitem__[T, *Ts](self, params: T | tuple[T, *Ts], /) -> TypeAlias:
|
38
38
|
iter_params = iter(params if isinstance(params, tuple) else (params,))
|
39
39
|
cls = next(iter_params)
|
40
40
|
return Annotated[cls, self(cls), *iter_params]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: python-injection
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.19.1
|
4
4
|
Summary: Fast and easy dependency injection framework.
|
5
5
|
Project-URL: Repository, https://github.com/100nm/python-injection
|
6
6
|
Author: remimd
|
@@ -103,4 +103,5 @@ if __name__ == "__main__":
|
|
103
103
|
* [**Entrypoint**](https://github.com/100nm/python-injection/tree/prod/documentation/entrypoint.md)
|
104
104
|
* [**Integrations**](https://github.com/100nm/python-injection/tree/prod/documentation/integrations)
|
105
105
|
* [**FastAPI**](https://github.com/100nm/python-injection/tree/prod/documentation/integrations/fastapi.md)
|
106
|
+
* [**What if my framework isn't listed?**](https://github.com/100nm/python-injection/tree/prod/documentation/integrations/unlisted-framework.md)
|
106
107
|
* [**Concrete example**](https://github.com/100nm/python-injection-example)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
injection/__init__.py,sha256=iJm0BbyGZw-Qr5e8d2C3n8-7FiVD-sy4LU_i_n3AgHY,1318
|
2
|
+
injection/__init__.pyi,sha256=2ndBULZyjN0SnyRml2gba9OOsTY0BhR3STEyvv1aZOA,11566
|
3
|
+
injection/entrypoint.py,sha256=NIILL_w3z2JKyn7S9XXwE0JtH2icuDWnAVpUY1fAMf8,4805
|
4
|
+
injection/exceptions.py,sha256=v57yMujiq6H_zwwn30A8UYEZX9R9k-bY8FnsdaimPM4,1025
|
5
|
+
injection/loaders.py,sha256=gKlJfe9nXCuB8r6j0RF9_2FHC6YplM8GQYsgRqyxYw8,7257
|
6
|
+
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
injection/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
injection/_core/asfunction.py,sha256=oVDJcM8buR1OnKJPDOfQ61bbrKVEPzfgtE_H74O1HN4,1718
|
9
|
+
injection/_core/descriptors.py,sha256=1OX6JnM8Ux14vW1JSW3FzPgKc2VMTKqJUYBGT3Ypafg,800
|
10
|
+
injection/_core/injectables.py,sha256=fxhiGv7qTCbUunhhd6a3ahosFmgznUFsEvqlwxi4gS4,6098
|
11
|
+
injection/_core/module.py,sha256=T9zvSOjMaPZiC_DCV7BIKOqCrmAHcYcleqgNro0MBgU,32624
|
12
|
+
injection/_core/scope.py,sha256=r094k1Vjvwm0hTf7AQGYrxxvqQgb7_CDVUKaHQ8wyeM,8772
|
13
|
+
injection/_core/slots.py,sha256=g9TG6CbqRzCsjg01iPyfRtTTUCJnnJOwcj9mJabH0dc,37
|
14
|
+
injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
injection/_core/common/asynchronous.py,sha256=nKY2_PAMFF2haC75Fwp8O9Zd-SDuenE6n3B-KccwXlw,1772
|
16
|
+
injection/_core/common/event.py,sha256=XjzV8gxtGlGvzZs_ykvoC60qmdpd3RN08Eiqz5QUwes,1236
|
17
|
+
injection/_core/common/invertible.py,sha256=gA_vw5nBjgp_w9MrDK5jMO8lhuOQWON8BbPpKzEuIY0,502
|
18
|
+
injection/_core/common/key.py,sha256=ghkZD-Y8Moz6SEPNgMh3xgsZUjDVq-XYAmXaCu5VuCA,80
|
19
|
+
injection/_core/common/lazy.py,sha256=L7C2dB5UBI--W5Kkvntp_jypYhudY3SHqs8rM6jxxsk,965
|
20
|
+
injection/_core/common/threading.py,sha256=kwRXNa9ocndIqeZA9kMHjEa8SBpHFcJARj1bgrWCpxE,225
|
21
|
+
injection/_core/common/type.py,sha256=SCDtmBv9qFvEf5o5tTgCuwMDfuo1fgjSW0bUqA8ACis,2251
|
22
|
+
injection/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
+
injection/ext/fastapi.py,sha256=fiy3-mZIIwGcql3Y5ekFX8_7hALzqXP5u40qbtNE73o,1441
|
24
|
+
injection/ext/fastapi.pyi,sha256=HLs7mfruIEFRrN_Xf8oCvSa4qwHWfwm6HHU_KMedXkE,185
|
25
|
+
injection/testing/__init__.py,sha256=bJ7WXBXrw4rHc91AFVFnOwFLWOlpvX9Oh2SnRQ_NESo,919
|
26
|
+
injection/testing/__init__.pyi,sha256=raGsGlxwbz3jkzJwA_5oCIE1emWINjT2UuwzbnqRb-0,577
|
27
|
+
python_injection-0.19.1.dist-info/METADATA,sha256=5skunJb1mk9ovTHiGRielQzeImyZOTRDcd4HLg6EaO0,4301
|
28
|
+
python_injection-0.19.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
29
|
+
python_injection-0.19.1.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
|
30
|
+
python_injection-0.19.1.dist-info/RECORD,,
|
@@ -1,29 +0,0 @@
|
|
1
|
-
injection/__init__.py,sha256=7ZRUlO5EEPWO7IlbYHD-8DOX-cg4Np4nYq5fpw-U56o,1259
|
2
|
-
injection/__init__.pyi,sha256=94F3A7lPmEyaJtsetVQpmS33LiY-BpymOLcFA6xvFBk,10964
|
3
|
-
injection/entrypoint.py,sha256=12b0_zHAFxHCerAoJTIHkhqi3mLkgheECYAaCUZv_DU,4751
|
4
|
-
injection/exceptions.py,sha256=v57yMujiq6H_zwwn30A8UYEZX9R9k-bY8FnsdaimPM4,1025
|
5
|
-
injection/loaders.py,sha256=gKlJfe9nXCuB8r6j0RF9_2FHC6YplM8GQYsgRqyxYw8,7257
|
6
|
-
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
injection/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
injection/_core/descriptors.py,sha256=RRng9lx-ET6An1d_244rAv4iLUTQUGvDh1ugLfImuW8,794
|
9
|
-
injection/_core/injectables.py,sha256=Rg1nxDkbcpeX4ELohrNVMguPhN36SNQuD0JKfyfL6bI,6192
|
10
|
-
injection/_core/module.py,sha256=lQFhfc9vDCiENkMvgkCzc-wW50uEl2bjKKBfRlR6nv8,32408
|
11
|
-
injection/_core/scope.py,sha256=NY6YWcIIXqBKTjXVsqsahxbw-bPJiL0CwHp6CyjBGJo,8753
|
12
|
-
injection/_core/slots.py,sha256=g9TG6CbqRzCsjg01iPyfRtTTUCJnnJOwcj9mJabH0dc,37
|
13
|
-
injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
injection/_core/common/asynchronous.py,sha256=lx1Ce3o6K00vzrZNRZUuf7wWlUKrdV3M53YZGyxQhOk,1817
|
15
|
-
injection/_core/common/event.py,sha256=XjzV8gxtGlGvzZs_ykvoC60qmdpd3RN08Eiqz5QUwes,1236
|
16
|
-
injection/_core/common/invertible.py,sha256=gA_vw5nBjgp_w9MrDK5jMO8lhuOQWON8BbPpKzEuIY0,502
|
17
|
-
injection/_core/common/key.py,sha256=ghkZD-Y8Moz6SEPNgMh3xgsZUjDVq-XYAmXaCu5VuCA,80
|
18
|
-
injection/_core/common/lazy.py,sha256=L7C2dB5UBI--W5Kkvntp_jypYhudY3SHqs8rM6jxxsk,965
|
19
|
-
injection/_core/common/threading.py,sha256=EsIvJl1brMsi551zzMILsMCXNHYUkQP22Mg4FZhp0hw,211
|
20
|
-
injection/_core/common/type.py,sha256=SCDtmBv9qFvEf5o5tTgCuwMDfuo1fgjSW0bUqA8ACis,2251
|
21
|
-
injection/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
-
injection/ext/fastapi.py,sha256=YdCVO1WgZRhv0CFrDnIdsbeRprtcHb-snIL4B4mpLnk,1388
|
23
|
-
injection/ext/fastapi.pyi,sha256=HLs7mfruIEFRrN_Xf8oCvSa4qwHWfwm6HHU_KMedXkE,185
|
24
|
-
injection/testing/__init__.py,sha256=bJ7WXBXrw4rHc91AFVFnOwFLWOlpvX9Oh2SnRQ_NESo,919
|
25
|
-
injection/testing/__init__.pyi,sha256=raGsGlxwbz3jkzJwA_5oCIE1emWINjT2UuwzbnqRb-0,577
|
26
|
-
python_injection-0.18.14.dist-info/METADATA,sha256=jtUZE1HuKfARdckxvXvKbw-xSnBuLEq0KTi5gmZZx2c,4155
|
27
|
-
python_injection-0.18.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
28
|
-
python_injection-0.18.14.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
|
29
|
-
python_injection-0.18.14.dist-info/RECORD,,
|
File without changes
|
File without changes
|