python-injection 0.14.0__py3-none-any.whl → 0.14.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__.pyi +11 -4
- injection/_core/hook.py +0 -1
- injection/_core/module.py +32 -25
- injection/_core/scope.py +2 -5
- injection/testing/__init__.py +2 -2
- injection/testing/__init__.pyi +1 -1
- injection/utils.py +2 -2
- {python_injection-0.14.0.dist-info → python_injection-0.14.1.dist-info}/METADATA +4 -1
- {python_injection-0.14.0.dist-info → python_injection-0.14.1.dist-info}/RECORD +10 -10
- {python_injection-0.14.0.dist-info → python_injection-0.14.1.dist-info}/WHEEL +0 -0
injection/__init__.pyi
CHANGED
@@ -10,6 +10,7 @@ from ._core.common.type import InputType as _InputType
|
|
10
10
|
from ._core.common.type import TypeInfo as _TypeInfo
|
11
11
|
from ._core.module import InjectableFactory as _InjectableFactory
|
12
12
|
from ._core.module import ModeStr, PriorityStr
|
13
|
+
from ._core.module import Recipe as _Recipe
|
13
14
|
|
14
15
|
__MODULE: Final[Module] = ...
|
15
16
|
|
@@ -91,7 +92,7 @@ class Module:
|
|
91
92
|
|
92
93
|
def injectable[**P, T](
|
93
94
|
self,
|
94
|
-
wrapped:
|
95
|
+
wrapped: _Recipe[P, T] = ...,
|
95
96
|
/,
|
96
97
|
*,
|
97
98
|
cls: _InjectableFactory[T] = ...,
|
@@ -107,7 +108,7 @@ class Module:
|
|
107
108
|
|
108
109
|
def singleton[**P, T](
|
109
110
|
self,
|
110
|
-
wrapped:
|
111
|
+
wrapped: _Recipe[P, T] = ...,
|
111
112
|
/,
|
112
113
|
*,
|
113
114
|
inject: bool = ...,
|
@@ -176,6 +177,12 @@ class Module:
|
|
176
177
|
/,
|
177
178
|
threadsafe: bool = ...,
|
178
179
|
) -> Callable[P, T]: ...
|
180
|
+
def make_async_factory[T](
|
181
|
+
self,
|
182
|
+
wrapped: type[T],
|
183
|
+
/,
|
184
|
+
threadsafe: bool = ...,
|
185
|
+
) -> Callable[..., Awaitable[T]]: ...
|
179
186
|
async def afind_instance[T](self, cls: _InputType[T]) -> T: ...
|
180
187
|
def find_instance[T](self, cls: _InputType[T]) -> T:
|
181
188
|
"""
|
@@ -281,7 +288,7 @@ class Module:
|
|
281
288
|
module: Module,
|
282
289
|
*,
|
283
290
|
priority: Priority | PriorityStr = ...,
|
284
|
-
) -> Iterator[
|
291
|
+
) -> Iterator[Self]:
|
285
292
|
"""
|
286
293
|
Context manager or decorator for temporary use of a module.
|
287
294
|
"""
|
@@ -305,7 +312,7 @@ class Module:
|
|
305
312
|
"""
|
306
313
|
|
307
314
|
@contextmanager
|
308
|
-
def load_profile(self, *names: str) -> Iterator[
|
315
|
+
def load_profile(self, *names: str) -> Iterator[Self]: ...
|
309
316
|
async def all_ready(self) -> None: ...
|
310
317
|
def add_logger(self, logger: Logger) -> Self: ...
|
311
318
|
@classmethod
|
injection/_core/hook.py
CHANGED
injection/_core/module.py
CHANGED
@@ -3,10 +3,12 @@ from __future__ import annotations
|
|
3
3
|
from abc import ABC, abstractmethod
|
4
4
|
from collections import OrderedDict, deque
|
5
5
|
from collections.abc import (
|
6
|
+
AsyncGenerator,
|
6
7
|
AsyncIterator,
|
7
8
|
Awaitable,
|
8
9
|
Callable,
|
9
10
|
Collection,
|
11
|
+
Generator,
|
10
12
|
Iterable,
|
11
13
|
Iterator,
|
12
14
|
Mapping,
|
@@ -360,6 +362,14 @@ class Priority(StrEnum):
|
|
360
362
|
|
361
363
|
type PriorityStr = Literal["low", "high"]
|
362
364
|
|
365
|
+
type ContextManagerLikeRecipe[**P, T] = (
|
366
|
+
Callable[P, ContextManager[T]] | Callable[P, AsyncContextManager[T]]
|
367
|
+
)
|
368
|
+
type GeneratorRecipe[**P, T] = (
|
369
|
+
Callable[P, Generator[T, Any, Any]] | Callable[P, AsyncGenerator[T, Any]]
|
370
|
+
)
|
371
|
+
type Recipe[**P, T] = Callable[P, T] | Callable[P, Awaitable[T]]
|
372
|
+
|
363
373
|
|
364
374
|
@dataclass(eq=False, frozen=True, slots=True)
|
365
375
|
class Module(Broker, EventListener):
|
@@ -411,7 +421,7 @@ class Module(Broker, EventListener):
|
|
411
421
|
|
412
422
|
def injectable[**P, T](
|
413
423
|
self,
|
414
|
-
wrapped:
|
424
|
+
wrapped: Recipe[P, T] | None = None,
|
415
425
|
/,
|
416
426
|
*,
|
417
427
|
cls: InjectableFactory[T] = SimpleInjectable,
|
@@ -420,9 +430,7 @@ class Module(Broker, EventListener):
|
|
420
430
|
on: TypeInfo[T] = (),
|
421
431
|
mode: Mode | ModeStr = Mode.get_default(),
|
422
432
|
) -> Any:
|
423
|
-
def decorator(
|
424
|
-
wp: Callable[P, T] | Callable[P, Awaitable[T]],
|
425
|
-
) -> Callable[P, T] | Callable[P, Awaitable[T]]:
|
433
|
+
def decorator(wp: Recipe[P, T]) -> Recipe[P, T]:
|
426
434
|
factory = extract_caller(self.make_injected_function(wp) if inject else wp)
|
427
435
|
hints = on if ignore_type_hint else (wp, on)
|
428
436
|
updater = Updater(
|
@@ -447,23 +455,10 @@ class Module(Broker, EventListener):
|
|
447
455
|
mode: Mode | ModeStr = Mode.get_default(),
|
448
456
|
) -> Any:
|
449
457
|
def decorator(
|
450
|
-
wrapped:
|
451
|
-
|
452
|
-
| Callable[P, Iterator[T]]
|
453
|
-
| Callable[P, AsyncIterator[T]],
|
454
|
-
) -> (
|
455
|
-
Callable[P, T]
|
456
|
-
| Callable[P, Awaitable[T]]
|
457
|
-
| Callable[P, Iterator[T]]
|
458
|
-
| Callable[P, AsyncIterator[T]]
|
459
|
-
):
|
458
|
+
wrapped: Recipe[P, T] | GeneratorRecipe[P, T],
|
459
|
+
) -> Recipe[P, T] | GeneratorRecipe[P, T]:
|
460
460
|
injectable_class: Callable[[Caller[P, Any], str], Injectable[T]]
|
461
|
-
wrapper:
|
462
|
-
Callable[P, T]
|
463
|
-
| Callable[P, Awaitable[T]]
|
464
|
-
| Callable[P, ContextManager[T]]
|
465
|
-
| Callable[P, AsyncContextManager[T]]
|
466
|
-
)
|
461
|
+
wrapper: Recipe[P, T] | ContextManagerLikeRecipe[P, T]
|
467
462
|
|
468
463
|
if isasyncgenfunction(wrapped):
|
469
464
|
hint = get_yield_hint(wrapped)
|
@@ -588,6 +583,18 @@ class Module(Broker, EventListener):
|
|
588
583
|
|
589
584
|
return SyncInjectedFunction(metadata)
|
590
585
|
|
586
|
+
def make_async_factory[T](
|
587
|
+
self,
|
588
|
+
wrapped: type[T],
|
589
|
+
/,
|
590
|
+
threadsafe: bool = False,
|
591
|
+
) -> Callable[..., Awaitable[T]]:
|
592
|
+
factory: InjectedFunction[..., T] = self.make_injected_function(
|
593
|
+
wrapped,
|
594
|
+
threadsafe,
|
595
|
+
)
|
596
|
+
return factory.__inject_metadata__.acall
|
597
|
+
|
591
598
|
async def afind_instance[T](self, cls: InputType[T]) -> T:
|
592
599
|
injectable = self[cls]
|
593
600
|
return await injectable.aget_instance()
|
@@ -739,11 +746,11 @@ class Module(Broker, EventListener):
|
|
739
746
|
module: Module,
|
740
747
|
*,
|
741
748
|
priority: Priority | PriorityStr = Priority.get_default(),
|
742
|
-
) -> Iterator[
|
749
|
+
) -> Iterator[Self]:
|
743
750
|
self.use(module, priority=priority)
|
744
751
|
|
745
752
|
try:
|
746
|
-
yield
|
753
|
+
yield self
|
747
754
|
finally:
|
748
755
|
self.stop_using(module)
|
749
756
|
|
@@ -762,7 +769,7 @@ class Module(Broker, EventListener):
|
|
762
769
|
|
763
770
|
return self
|
764
771
|
|
765
|
-
def load_profile(self, *names: str) -> ContextManager[
|
772
|
+
def load_profile(self, *names: str) -> ContextManager[Self]:
|
766
773
|
modules = tuple(self.from_name(name) for name in names)
|
767
774
|
|
768
775
|
for module in modules:
|
@@ -773,8 +780,8 @@ class Module(Broker, EventListener):
|
|
773
780
|
del module, modules
|
774
781
|
|
775
782
|
@contextmanager
|
776
|
-
def cleaner() -> Iterator[
|
777
|
-
yield
|
783
|
+
def cleaner() -> Iterator[Self]:
|
784
|
+
yield self
|
778
785
|
self.unlock().init_modules()
|
779
786
|
|
780
787
|
return cleaner()
|
injection/_core/scope.py
CHANGED
@@ -121,11 +121,8 @@ def _bind_scope(name: str, scope: Scope, shared: bool) -> Iterator[None]:
|
|
121
121
|
f"Scope `{name}` is already defined in the current context."
|
122
122
|
)
|
123
123
|
|
124
|
-
strategy =
|
125
|
-
|
126
|
-
)
|
127
|
-
|
128
|
-
with strategy:
|
124
|
+
strategy = state.bind_shared_scope if shared else state.bind_contextual_scope
|
125
|
+
with strategy(scope):
|
129
126
|
yield
|
130
127
|
|
131
128
|
|
injection/testing/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import ContextManager, Final
|
2
2
|
|
3
|
-
from injection import mod
|
3
|
+
from injection import Module, mod
|
4
4
|
from injection.utils import load_profile
|
5
5
|
|
6
6
|
__all__ = (
|
@@ -23,5 +23,5 @@ test_scoped = mod(_TEST_PROFILE_NAME).scoped
|
|
23
23
|
test_singleton = mod(_TEST_PROFILE_NAME).singleton
|
24
24
|
|
25
25
|
|
26
|
-
def load_test_profile(*names: str) -> ContextManager[
|
26
|
+
def load_test_profile(*names: str) -> ContextManager[Module]:
|
27
27
|
return load_profile(_TEST_PROFILE_NAME, *names)
|
injection/testing/__init__.pyi
CHANGED
@@ -11,7 +11,7 @@ test_injectable = __MODULE.injectable
|
|
11
11
|
test_scoped = __MODULE.scoped
|
12
12
|
test_singleton = __MODULE.singleton
|
13
13
|
|
14
|
-
def load_test_profile(*names: str) -> ContextManager[
|
14
|
+
def load_test_profile(*names: str) -> ContextManager[Module]:
|
15
15
|
"""
|
16
16
|
Context manager or decorator for temporary use test module.
|
17
17
|
"""
|
injection/utils.py
CHANGED
@@ -5,13 +5,13 @@ from pkgutil import walk_packages
|
|
5
5
|
from types import ModuleType as PythonModule
|
6
6
|
from typing import ContextManager
|
7
7
|
|
8
|
+
from injection import Module, mod
|
8
9
|
from injection import __name__ as injection_package_name
|
9
|
-
from injection import mod
|
10
10
|
|
11
11
|
__all__ = ("load_modules_with_keywords", "load_packages", "load_profile")
|
12
12
|
|
13
13
|
|
14
|
-
def load_profile(*names: str) -> ContextManager[
|
14
|
+
def load_profile(*names: str) -> ContextManager[Module]:
|
15
15
|
"""
|
16
16
|
Injection module initialization function based on profile name.
|
17
17
|
A profile name is equivalent to an injection module name.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: python-injection
|
3
|
-
Version: 0.14.
|
3
|
+
Version: 0.14.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
|
@@ -78,6 +78,9 @@ if __name__ == "__main__":
|
|
78
78
|
|
79
79
|
## Resources
|
80
80
|
|
81
|
+
> ⚠️ The package isn't threadsafe, for better performance in single-threaded applications and those using `asyncio`.
|
82
|
+
> So remember to use `threading.Lock` if you're writing a multithreaded program.
|
83
|
+
|
81
84
|
* [**Basic usage**](https://github.com/100nm/python-injection/tree/prod/documentation/basic-usage.md)
|
82
85
|
* [**Scoped dependencies**](https://github.com/100nm/python-injection/tree/prod/documentation/scoped-dependencies.md)
|
83
86
|
* [**Testing**](https://github.com/100nm/python-injection/tree/prod/documentation/testing.md)
|
@@ -1,14 +1,14 @@
|
|
1
1
|
injection/__init__.py,sha256=X0vIAoN4MDlhR7YIkup1qHgqbOkwZ3PWgdSi7h-udaM,1049
|
2
|
-
injection/__init__.pyi,sha256=
|
2
|
+
injection/__init__.pyi,sha256=6B5GdRNaAJ15Q-QAL8nNpTBVIKEUPJAwWIlCSjOkkJ8,10058
|
3
3
|
injection/exceptions.py,sha256=T__732aXxWWUz0sKc39ySteyolCS5tpqQC0oCnzUF2E,917
|
4
4
|
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
injection/utils.py,sha256=
|
5
|
+
injection/utils.py,sha256=Lr0qHaq3_1AkUoAaw2XmMNie_alwYTeTrRlO22FeCnk,2762
|
6
6
|
injection/_core/__init__.py,sha256=XERocCxCZBxPGIaOR37yeiQOZyvjHQ6a4rgRmlkUSuU,1367
|
7
7
|
injection/_core/descriptors.py,sha256=7fSHlgAqmgR_Uta8KocBapOt1Xyj2dI7RY9ZdoStTzw,726
|
8
|
-
injection/_core/hook.py,sha256=
|
8
|
+
injection/_core/hook.py,sha256=rJyaSwFAHM8qizWANPUSt5KzWdjxc5oJ2U8hcGeZjU8,3097
|
9
9
|
injection/_core/injectables.py,sha256=GIumNp0TXf8Voxe1sCPhcqq2gyw4E_hl7I45IJ_tyHE,4512
|
10
|
-
injection/_core/module.py,sha256=
|
11
|
-
injection/_core/scope.py,sha256=
|
10
|
+
injection/_core/module.py,sha256=Dxpdtsft-BaaPRj2v1YFepF1y1s7QINoa9iDxQLGJjM,31154
|
11
|
+
injection/_core/scope.py,sha256=pwOqVKOUM_ZteNScgp-hLqyOHg5Ew75jWlfWLLD2PU8,5437
|
12
12
|
injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
injection/_core/common/asynchronous.py,sha256=9bQDVRE6eqo9K0d5H9RzyFalf0WGoGP7cDrKDGbvZPI,1500
|
14
14
|
injection/_core/common/event.py,sha256=XjzV8gxtGlGvzZs_ykvoC60qmdpd3RN08Eiqz5QUwes,1236
|
@@ -18,8 +18,8 @@ injection/_core/common/lazy.py,sha256=6xh5h0lmaNvl32V0WoX4VCTsNJ3zUJdWVqpLJ_YeII
|
|
18
18
|
injection/_core/common/type.py,sha256=QbBBhJp7i1p6gLzWX0TgofvfG7yDH-gHfEQcssVZeHo,2186
|
19
19
|
injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
20
|
injection/integrations/fastapi.py,sha256=YHSs85_3m6TUVtOwUcV157b3UZJQIw_aXWAg199a-YE,594
|
21
|
-
injection/testing/__init__.py,sha256=
|
22
|
-
injection/testing/__init__.pyi,sha256=
|
23
|
-
python_injection-0.14.
|
24
|
-
python_injection-0.14.
|
25
|
-
python_injection-0.14.
|
21
|
+
injection/testing/__init__.py,sha256=Bh3JqEXw62-JnUnspOXr2jpjGXZJ_K_K9CgfD7dPZeQ,793
|
22
|
+
injection/testing/__init__.pyi,sha256=1h9zNGghxlo4D1jAx5s8EHk54mn7o-qO7WgJa6hwX6U,484
|
23
|
+
python_injection-0.14.1.dist-info/METADATA,sha256=CMClwSxU8s_yCBYsduNEXc1426OeyWQzGFHTlQxe1eo,3199
|
24
|
+
python_injection-0.14.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
25
|
+
python_injection-0.14.1.dist-info/RECORD,,
|
File without changes
|