python-injection 0.9.0__py3-none-any.whl → 0.9.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 +10 -9
- injection/__init__.pyi +22 -9
- injection/common/tools/threading.py +4 -2
- injection/common/tools/type.py +6 -4
- injection/core/module.py +39 -18
- injection/integrations/blacksheep.py +3 -3
- injection/testing/__init__.py +38 -0
- injection/testing/__init__.pyi +22 -0
- {python_injection-0.9.0.dist-info → python_injection-0.9.1.dist-info}/METADATA +2 -2
- python_injection-0.9.1.dist-info/RECORD +21 -0
- python_injection-0.9.0.dist-info/RECORD +0 -19
- {python_injection-0.9.0.dist-info → python_injection-0.9.1.dist-info}/WHEEL +0 -0
injection/__init__.py
CHANGED
|
@@ -7,7 +7,6 @@ __all__ = (
|
|
|
7
7
|
"InjectableMode",
|
|
8
8
|
"Module",
|
|
9
9
|
"ModulePriority",
|
|
10
|
-
"default_module",
|
|
11
10
|
"get_instance",
|
|
12
11
|
"get_lazy_instance",
|
|
13
12
|
"inject",
|
|
@@ -17,12 +16,14 @@ __all__ = (
|
|
|
17
16
|
"singleton",
|
|
18
17
|
)
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
_module = Module.default()
|
|
21
20
|
|
|
22
|
-
get_instance =
|
|
23
|
-
get_lazy_instance =
|
|
24
|
-
inject =
|
|
25
|
-
injectable =
|
|
26
|
-
set_constant =
|
|
27
|
-
should_be_injectable =
|
|
28
|
-
singleton =
|
|
21
|
+
get_instance = _module.get_instance
|
|
22
|
+
get_lazy_instance = _module.get_lazy_instance
|
|
23
|
+
inject = _module.inject
|
|
24
|
+
injectable = _module.injectable
|
|
25
|
+
set_constant = _module.set_constant
|
|
26
|
+
should_be_injectable = _module.should_be_injectable
|
|
27
|
+
singleton = _module.singleton
|
|
28
|
+
|
|
29
|
+
del _module
|
injection/__init__.pyi
CHANGED
|
@@ -6,7 +6,6 @@ from types import UnionType
|
|
|
6
6
|
from typing import (
|
|
7
7
|
Any,
|
|
8
8
|
ContextManager,
|
|
9
|
-
Final,
|
|
10
9
|
Protocol,
|
|
11
10
|
Self,
|
|
12
11
|
final,
|
|
@@ -19,15 +18,17 @@ from .core import InjectableFactory
|
|
|
19
18
|
from .core import ModeStr as InjectableModeStr
|
|
20
19
|
from .core import PriorityStr as ModulePriorityStr
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
_module: Module = ...
|
|
23
22
|
|
|
24
|
-
get_instance =
|
|
25
|
-
get_lazy_instance =
|
|
26
|
-
inject =
|
|
27
|
-
injectable =
|
|
28
|
-
set_constant =
|
|
29
|
-
should_be_injectable =
|
|
30
|
-
singleton =
|
|
23
|
+
get_instance = _module.get_instance
|
|
24
|
+
get_lazy_instance = _module.get_lazy_instance
|
|
25
|
+
inject = _module.inject
|
|
26
|
+
injectable = _module.injectable
|
|
27
|
+
set_constant = _module.set_constant
|
|
28
|
+
should_be_injectable = _module.should_be_injectable
|
|
29
|
+
singleton = _module.singleton
|
|
30
|
+
|
|
31
|
+
del _module
|
|
31
32
|
|
|
32
33
|
@final
|
|
33
34
|
class Module:
|
|
@@ -178,6 +179,18 @@ class Module:
|
|
|
178
179
|
Function to unlock the module by deleting cached instances of singletons.
|
|
179
180
|
"""
|
|
180
181
|
|
|
182
|
+
@classmethod
|
|
183
|
+
def from_name(cls, name: str) -> Self:
|
|
184
|
+
"""
|
|
185
|
+
Class method for getting or creating a module by name.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def default(cls) -> Self:
|
|
190
|
+
"""
|
|
191
|
+
Class method for getting the default module.
|
|
192
|
+
"""
|
|
193
|
+
|
|
181
194
|
@final
|
|
182
195
|
class ModulePriority(StrEnum):
|
|
183
196
|
LOW = ...
|
injection/common/tools/type.py
CHANGED
|
@@ -21,11 +21,13 @@ class TypeReport[T](NamedTuple):
|
|
|
21
21
|
args: tuple[Any, ...]
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
def type(self) -> type[T]:
|
|
25
|
+
origin = self.origin
|
|
26
|
+
|
|
27
|
+
if args := self.args:
|
|
28
|
+
return origin[*args]
|
|
27
29
|
|
|
28
|
-
return
|
|
30
|
+
return origin
|
|
29
31
|
|
|
30
32
|
@property
|
|
31
33
|
def no_args(self) -> Self:
|
injection/core/module.py
CHANGED
|
@@ -78,10 +78,10 @@ class ContainerDependenciesUpdated(ContainerEvent):
|
|
|
78
78
|
|
|
79
79
|
def __str__(self) -> str:
|
|
80
80
|
length = len(self.reports)
|
|
81
|
-
|
|
81
|
+
formatted_types = ", ".join(f"`{report.type}`" for report in self.reports)
|
|
82
82
|
return (
|
|
83
|
-
f"{length} container dependenc{'ies' if length > 1 else 'y'} have
|
|
84
|
-
f"updated{f': {
|
|
83
|
+
f"{length} container dependenc{'ies' if length > 1 else 'y'} have "
|
|
84
|
+
f"been updated{f': {formatted_types}' if formatted_types else ''}."
|
|
85
85
|
)
|
|
86
86
|
|
|
87
87
|
|
|
@@ -174,7 +174,7 @@ class NewInjectable[T](BaseInjectable[T]):
|
|
|
174
174
|
class SingletonInjectable[T](BaseInjectable[T]):
|
|
175
175
|
__slots__ = ("__dict__",)
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
__key: ClassVar[str] = "$instance"
|
|
178
178
|
|
|
179
179
|
@property
|
|
180
180
|
def cache(self) -> MutableMapping[str, Any]:
|
|
@@ -182,18 +182,18 @@ class SingletonInjectable[T](BaseInjectable[T]):
|
|
|
182
182
|
|
|
183
183
|
@property
|
|
184
184
|
def is_locked(self) -> bool:
|
|
185
|
-
return self.
|
|
185
|
+
return self.__key in self.cache
|
|
186
186
|
|
|
187
187
|
def unlock(self):
|
|
188
188
|
self.cache.clear()
|
|
189
189
|
|
|
190
190
|
def get_instance(self) -> T:
|
|
191
191
|
with suppress(KeyError):
|
|
192
|
-
return self.cache[self.
|
|
192
|
+
return self.cache[self.__key]
|
|
193
193
|
|
|
194
194
|
with synchronized():
|
|
195
195
|
instance = self.factory()
|
|
196
|
-
self.cache[self.
|
|
196
|
+
self.cache[self.__key] = instance
|
|
197
197
|
|
|
198
198
|
return instance
|
|
199
199
|
|
|
@@ -340,7 +340,7 @@ class Container(Broker):
|
|
|
340
340
|
else:
|
|
341
341
|
if mode == current_mode and mode != Mode.OVERRIDE:
|
|
342
342
|
raise RuntimeError(
|
|
343
|
-
f"An injectable already exists for the class `{report.
|
|
343
|
+
f"An injectable already exists for the class `{report.type}`."
|
|
344
344
|
)
|
|
345
345
|
|
|
346
346
|
elif rank < current_mode.rank:
|
|
@@ -368,16 +368,27 @@ type PriorityStr = Literal["low", "high"]
|
|
|
368
368
|
type InjectableFactory[T] = Callable[[Callable[..., T]], Injectable[T]]
|
|
369
369
|
|
|
370
370
|
|
|
371
|
-
@dataclass(
|
|
371
|
+
@dataclass(eq=False, frozen=True, slots=True)
|
|
372
372
|
class Module(EventListener, Broker):
|
|
373
373
|
name: str | None = field(default=None)
|
|
374
|
-
__channel: EventChannel = field(
|
|
375
|
-
|
|
374
|
+
__channel: EventChannel = field(
|
|
375
|
+
default_factory=EventChannel,
|
|
376
|
+
init=False,
|
|
377
|
+
repr=False,
|
|
378
|
+
)
|
|
379
|
+
__container: Container = field(
|
|
380
|
+
default_factory=Container,
|
|
381
|
+
init=False,
|
|
382
|
+
repr=False,
|
|
383
|
+
)
|
|
376
384
|
__modules: OrderedDict[Module, None] = field(
|
|
377
385
|
default_factory=OrderedDict,
|
|
378
386
|
init=False,
|
|
387
|
+
repr=False,
|
|
379
388
|
)
|
|
380
389
|
|
|
390
|
+
__instances: ClassVar[dict[str, Module]] = {}
|
|
391
|
+
|
|
381
392
|
def __post_init__(self):
|
|
382
393
|
self.__container.add_listener(self)
|
|
383
394
|
|
|
@@ -394,9 +405,6 @@ class Module(EventListener, Broker):
|
|
|
394
405
|
def __contains__(self, cls: type | UnionType, /) -> bool:
|
|
395
406
|
return any(cls in broker for broker in self.__brokers)
|
|
396
407
|
|
|
397
|
-
def __str__(self) -> str:
|
|
398
|
-
return self.name or object.__str__(self)
|
|
399
|
-
|
|
400
408
|
@property
|
|
401
409
|
def is_locked(self) -> bool:
|
|
402
410
|
return any(broker.is_locked for broker in self.__brokers)
|
|
@@ -468,7 +476,7 @@ class Module(EventListener, Broker):
|
|
|
468
476
|
|
|
469
477
|
function = InjectedFunction(wp)
|
|
470
478
|
|
|
471
|
-
@function.on_setup
|
|
479
|
+
@function.on_setup(block=False)
|
|
472
480
|
def listen():
|
|
473
481
|
function.update(self)
|
|
474
482
|
self.add_listener(function)
|
|
@@ -611,6 +619,19 @@ class Module(EventListener, Broker):
|
|
|
611
619
|
f"`{module}` can't be found in the modules used by `{self}`."
|
|
612
620
|
) from exc
|
|
613
621
|
|
|
622
|
+
@classmethod
|
|
623
|
+
def from_name(cls, name: str) -> Self:
|
|
624
|
+
with suppress(KeyError):
|
|
625
|
+
return cls.__instances[name]
|
|
626
|
+
|
|
627
|
+
instance = cls(name)
|
|
628
|
+
cls.__instances[name] = instance
|
|
629
|
+
return instance
|
|
630
|
+
|
|
631
|
+
@classmethod
|
|
632
|
+
def default(cls) -> Self:
|
|
633
|
+
return cls.from_name("default")
|
|
634
|
+
|
|
614
635
|
|
|
615
636
|
"""
|
|
616
637
|
InjectedFunction
|
|
@@ -641,7 +662,7 @@ class Dependencies:
|
|
|
641
662
|
|
|
642
663
|
@classmethod
|
|
643
664
|
def from_mapping(cls, mapping: Mapping[str, Injectable]) -> Self:
|
|
644
|
-
return cls(mapping
|
|
665
|
+
return cls(mapping)
|
|
645
666
|
|
|
646
667
|
@classmethod
|
|
647
668
|
def empty(cls) -> Self:
|
|
@@ -775,9 +796,9 @@ class InjectedFunction(EventListener):
|
|
|
775
796
|
self.__dependencies = Dependencies.resolve(self.signature, module, self.__owner)
|
|
776
797
|
return self
|
|
777
798
|
|
|
778
|
-
def on_setup(self, wrapped: Callable[[], Any] = None,
|
|
799
|
+
def on_setup(self, wrapped: Callable[[], Any] = None, /, *, block: bool = True):
|
|
779
800
|
def decorator(wp):
|
|
780
|
-
self.__setup_queue.put(wp)
|
|
801
|
+
self.__setup_queue.put(wp, block=block)
|
|
781
802
|
return wp
|
|
782
803
|
|
|
783
804
|
return decorator(wrapped) if wrapped else decorator
|
|
@@ -2,7 +2,7 @@ from typing import Any
|
|
|
2
2
|
|
|
3
3
|
from rodi import ContainerProtocol
|
|
4
4
|
|
|
5
|
-
from injection import Module
|
|
5
|
+
from injection import Module
|
|
6
6
|
|
|
7
7
|
__all__ = ("InjectionServices",)
|
|
8
8
|
|
|
@@ -14,8 +14,8 @@ class InjectionServices(ContainerProtocol):
|
|
|
14
14
|
|
|
15
15
|
__slots__ = ("__module",)
|
|
16
16
|
|
|
17
|
-
def __init__(self, module: Module =
|
|
18
|
-
self.__module = module
|
|
17
|
+
def __init__(self, module: Module = None):
|
|
18
|
+
self.__module = module or Module.default()
|
|
19
19
|
|
|
20
20
|
def __contains__(self, item: Any) -> bool:
|
|
21
21
|
return item in self.__module
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
|
|
3
|
+
from injection import Module, ModulePriority
|
|
4
|
+
|
|
5
|
+
__all__ = (
|
|
6
|
+
"set_test_constant",
|
|
7
|
+
"should_be_test_injectable",
|
|
8
|
+
"test_injectable",
|
|
9
|
+
"test_singleton",
|
|
10
|
+
"use_test_injectables",
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_test_module() -> Module:
|
|
15
|
+
return Module.from_name("testing")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_module = get_test_module()
|
|
19
|
+
|
|
20
|
+
set_test_constant = _module.set_constant
|
|
21
|
+
should_be_test_injectable = _module.should_be_injectable
|
|
22
|
+
test_injectable = _module.injectable
|
|
23
|
+
test_singleton = _module.singleton
|
|
24
|
+
|
|
25
|
+
del _module
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@contextmanager
|
|
29
|
+
def use_test_injectables(*, on: Module = None, test_module: Module = None):
|
|
30
|
+
on = on or Module.default()
|
|
31
|
+
test_module = test_module or get_test_module()
|
|
32
|
+
|
|
33
|
+
for module in (on, test_module):
|
|
34
|
+
module.unlock()
|
|
35
|
+
|
|
36
|
+
with on.use_temporarily(test_module, priority=ModulePriority.HIGH):
|
|
37
|
+
yield
|
|
38
|
+
on.unlock()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from contextlib import ContextDecorator
|
|
2
|
+
from typing import ContextManager
|
|
3
|
+
|
|
4
|
+
from injection import Module
|
|
5
|
+
|
|
6
|
+
_module: Module = ...
|
|
7
|
+
|
|
8
|
+
set_test_constant = _module.set_constant
|
|
9
|
+
should_be_test_injectable = _module.should_be_injectable
|
|
10
|
+
test_injectable = _module.injectable
|
|
11
|
+
test_singleton = _module.singleton
|
|
12
|
+
|
|
13
|
+
del _module
|
|
14
|
+
|
|
15
|
+
def use_test_injectables(
|
|
16
|
+
*,
|
|
17
|
+
on: Module = ...,
|
|
18
|
+
test_module: Module = ...,
|
|
19
|
+
) -> ContextManager | ContextDecorator:
|
|
20
|
+
"""
|
|
21
|
+
Context manager or decorator for temporary use test module.
|
|
22
|
+
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-injection
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Fast and easy dependency injection framework.
|
|
5
5
|
Home-page: https://github.com/100nm/python-injection
|
|
6
6
|
License: MIT
|
|
@@ -15,7 +15,7 @@ Description-Content-Type: text/markdown
|
|
|
15
15
|
|
|
16
16
|
# Basic usage
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Register an injectable
|
|
19
19
|
|
|
20
20
|
> **Note**: If the class needs dependencies, these will be resolved when the instance is retrieved.
|
|
21
21
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
injection/__init__.py,sha256=LhfwYFMBw6tJ7XA_C353w61OPt4IuQQgs3zIjrwMIz8,654
|
|
2
|
+
injection/__init__.pyi,sha256=dfIQAR8L8Yr7dM-DODR4czwUd2a7zzFQHzb8mr1Q6P0,6235
|
|
3
|
+
injection/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
injection/common/event.py,sha256=5Rdb2m3vAMCic8cQAVkStJDbrDrW_lk6kav8wYwmexM,1283
|
|
5
|
+
injection/common/invertible.py,sha256=noNcmJ96IQi0XJms0dyfrx_AvKZnQM0sZyxhc2l6qo0,527
|
|
6
|
+
injection/common/lazy.py,sha256=FEas6ewwOGWvRR8cflmyVvSLZd_-Fxd0QeIdvAM5I9c,1313
|
|
7
|
+
injection/common/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
injection/common/tools/threading.py,sha256=HlvP6k_-eZaK8JbB2b9PP171IZVe_0W2oMYsw3ebdKA,187
|
|
9
|
+
injection/common/tools/type.py,sha256=ThM3Z1_gHmsdT4Jp7PlZgJY0lsufc4InPO65485Ugsg,1739
|
|
10
|
+
injection/core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
|
|
11
|
+
injection/core/module.py,sha256=3FqU4XQgTNLI-VwpX1bKcRsLOaPeKSQ0sQuVsL_27I4,21625
|
|
12
|
+
injection/exceptions.py,sha256=RsWWiWwKSMU0vxXQqQSn6CKHLMrGu4SSzYUAy9OJRXk,626
|
|
13
|
+
injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
injection/integrations/blacksheep.py,sha256=82P_owhF3FKIJxxalnSic3AJnoOr1mkojkWMefpO6QI,731
|
|
15
|
+
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
injection/testing/__init__.py,sha256=xglKmIJgg2j1wt8qWJ_TtGfFyKmn7xE7b8kQhD2yEkQ,864
|
|
17
|
+
injection/testing/__init__.pyi,sha256=_u95cJVHBkt69HUvnu2bbfYWmi7GOH_1qyFyvC1PxBk,518
|
|
18
|
+
injection/utils.py,sha256=_79aiciimZpuoUTz5lojKySUMMzpkU-e7SotiHIFTI8,676
|
|
19
|
+
python_injection-0.9.1.dist-info/METADATA,sha256=6vDRDhsWCG-FbwiHs-pvslfia8Fpe2n7hWJPoxJJbhg,3572
|
|
20
|
+
python_injection-0.9.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
21
|
+
python_injection-0.9.1.dist-info/RECORD,,
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
injection/__init__.py,sha256=Bf6S99E2srD3752xlJf3uAdiGIzY2YHOZafcwEiwY70,739
|
|
2
|
-
injection/__init__.pyi,sha256=HEk1HXAmwtq2ZEFLf5A7VWhdpPVWVQpjsLip9JzepEY,6023
|
|
3
|
-
injection/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
injection/common/event.py,sha256=5Rdb2m3vAMCic8cQAVkStJDbrDrW_lk6kav8wYwmexM,1283
|
|
5
|
-
injection/common/invertible.py,sha256=noNcmJ96IQi0XJms0dyfrx_AvKZnQM0sZyxhc2l6qo0,527
|
|
6
|
-
injection/common/lazy.py,sha256=FEas6ewwOGWvRR8cflmyVvSLZd_-Fxd0QeIdvAM5I9c,1313
|
|
7
|
-
injection/common/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
injection/common/tools/threading.py,sha256=Urcy59Rp34psRWmzzQyNDu4Zm-DuCkPsp4qO1x_W4qQ,165
|
|
9
|
-
injection/common/tools/type.py,sha256=5Ixswd9-sSqJdmh9lTd3jADFHWgD0wZSwecVi1opeO0,1715
|
|
10
|
-
injection/core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
|
|
11
|
-
injection/core/module.py,sha256=nCa10YQu-o-W0jMt-EnjCuXc1VioqN5CZXK2EoS4zgo,21241
|
|
12
|
-
injection/exceptions.py,sha256=RsWWiWwKSMU0vxXQqQSn6CKHLMrGu4SSzYUAy9OJRXk,626
|
|
13
|
-
injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
injection/integrations/blacksheep.py,sha256=GQBZCyl_DNDuCJdV56EYaiYCXGDMmP66cEahRzUZpmc,737
|
|
15
|
-
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
injection/utils.py,sha256=_79aiciimZpuoUTz5lojKySUMMzpkU-e7SotiHIFTI8,676
|
|
17
|
-
python_injection-0.9.0.dist-info/METADATA,sha256=j_ikavu9sPJ2xkKcX6Vr8MmhoNayLEiVNLPQ99TzWNY,3570
|
|
18
|
-
python_injection-0.9.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
19
|
-
python_injection-0.9.0.dist-info/RECORD,,
|
|
File without changes
|