python-injection 0.12.0__tar.gz → 0.12.1.post0__tar.gz
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.
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/PKG-INFO +1 -1
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/asynchronous.py +1 -6
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/invertible.py +1 -2
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/lazy.py +0 -5
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/injectables.py +1 -9
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/module.py +23 -55
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/pyproject.toml +1 -1
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/README.md +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/__init__.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/__init__.pyi +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/__init__.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/__init__.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/event.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/threading.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/type.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/descriptors.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/hook.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/exceptions.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/integrations/__init__.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/integrations/fastapi.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/py.typed +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/testing/__init__.py +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/testing/__init__.pyi +0 -0
- {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/utils.py +0 -0
{python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/asynchronous.py
RENAMED
@@ -1,14 +1,13 @@
|
|
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 Any, NoReturn, Protocol,
|
4
|
+
from typing import Any, NoReturn, Protocol, runtime_checkable
|
5
5
|
|
6
6
|
|
7
7
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
8
8
|
class SimpleAwaitable[T](Awaitable[T]):
|
9
9
|
callable: Callable[..., Awaitable[T]]
|
10
10
|
|
11
|
-
@override
|
12
11
|
def __await__(self) -> Generator[Any, Any, T]:
|
13
12
|
return self.callable().__await__()
|
14
13
|
|
@@ -30,11 +29,9 @@ class Caller[**P, T](Protocol):
|
|
30
29
|
class AsyncCaller[**P, T](Caller[P, T]):
|
31
30
|
callable: Callable[P, Awaitable[T]]
|
32
31
|
|
33
|
-
@override
|
34
32
|
async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
35
33
|
return await self.callable(*args, **kwargs)
|
36
34
|
|
37
|
-
@override
|
38
35
|
def call(self, /, *args: P.args, **kwargs: P.kwargs) -> NoReturn:
|
39
36
|
raise RuntimeError(
|
40
37
|
"Synchronous call isn't supported for an asynchronous Callable."
|
@@ -45,10 +42,8 @@ class AsyncCaller[**P, T](Caller[P, T]):
|
|
45
42
|
class SyncCaller[**P, T](Caller[P, T]):
|
46
43
|
callable: Callable[P, T]
|
47
44
|
|
48
|
-
@override
|
49
45
|
async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
50
46
|
return self.callable(*args, **kwargs)
|
51
47
|
|
52
|
-
@override
|
53
48
|
def call(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
54
49
|
return self.callable(*args, **kwargs)
|
{python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/invertible.py
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
from abc import abstractmethod
|
2
2
|
from collections.abc import Callable
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Protocol,
|
4
|
+
from typing import Protocol, runtime_checkable
|
5
5
|
|
6
6
|
|
7
7
|
@runtime_checkable
|
@@ -15,6 +15,5 @@ class Invertible[T](Protocol):
|
|
15
15
|
class SimpleInvertible[T](Invertible[T]):
|
16
16
|
callable: Callable[..., T]
|
17
17
|
|
18
|
-
@override
|
19
18
|
def __invert__(self) -> T:
|
20
19
|
return self.callable()
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from collections.abc import Callable, Iterator, Mapping
|
2
2
|
from types import MappingProxyType
|
3
|
-
from typing import override
|
4
3
|
|
5
4
|
from injection._core.common.invertible import Invertible
|
6
5
|
|
@@ -14,7 +13,6 @@ class Lazy[T](Invertible[T]):
|
|
14
13
|
def __init__(self, factory: Callable[..., T]) -> None:
|
15
14
|
self.__setup_cache(factory)
|
16
15
|
|
17
|
-
@override
|
18
16
|
def __invert__(self) -> T:
|
19
17
|
return next(self.__iterator)
|
20
18
|
|
@@ -44,15 +42,12 @@ class LazyMapping[K, V](Mapping[K, V]):
|
|
44
42
|
def __init__(self, iterator: Iterator[tuple[K, V]]) -> None:
|
45
43
|
self.__lazy = Lazy(lambda: MappingProxyType(dict(iterator)))
|
46
44
|
|
47
|
-
@override
|
48
45
|
def __getitem__(self, key: K, /) -> V:
|
49
46
|
return (~self.__lazy)[key]
|
50
47
|
|
51
|
-
@override
|
52
48
|
def __iter__(self) -> Iterator[K]:
|
53
49
|
yield from ~self.__lazy
|
54
50
|
|
55
|
-
@override
|
56
51
|
def __len__(self) -> int:
|
57
52
|
return len(~self.__lazy)
|
58
53
|
|
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
|
|
2
2
|
from collections.abc import MutableMapping
|
3
3
|
from contextlib import suppress
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import Any, ClassVar, NoReturn, Protocol,
|
5
|
+
from typing import Any, ClassVar, NoReturn, Protocol, runtime_checkable
|
6
6
|
|
7
7
|
from injection._core.common.asynchronous import Caller
|
8
8
|
from injection._core.common.threading import synchronized
|
@@ -37,11 +37,9 @@ class BaseInjectable[T](Injectable[T], ABC):
|
|
37
37
|
class SimpleInjectable[T](BaseInjectable[T]):
|
38
38
|
__slots__ = ()
|
39
39
|
|
40
|
-
@override
|
41
40
|
async def aget_instance(self) -> T:
|
42
41
|
return await self.factory.acall()
|
43
42
|
|
44
|
-
@override
|
45
43
|
def get_instance(self) -> T:
|
46
44
|
return self.factory.call()
|
47
45
|
|
@@ -56,15 +54,12 @@ class SingletonInjectable[T](BaseInjectable[T]):
|
|
56
54
|
return self.__dict__
|
57
55
|
|
58
56
|
@property
|
59
|
-
@override
|
60
57
|
def is_locked(self) -> bool:
|
61
58
|
return self.__key in self.cache
|
62
59
|
|
63
|
-
@override
|
64
60
|
def unlock(self) -> None:
|
65
61
|
self.cache.clear()
|
66
62
|
|
67
|
-
@override
|
68
63
|
async def aget_instance(self) -> T:
|
69
64
|
with suppress(KeyError):
|
70
65
|
return self.__check_instance()
|
@@ -75,7 +70,6 @@ class SingletonInjectable[T](BaseInjectable[T]):
|
|
75
70
|
|
76
71
|
return instance
|
77
72
|
|
78
|
-
@override
|
79
73
|
def get_instance(self) -> T:
|
80
74
|
with suppress(KeyError):
|
81
75
|
return self.__check_instance()
|
@@ -97,10 +91,8 @@ class SingletonInjectable[T](BaseInjectable[T]):
|
|
97
91
|
class ShouldBeInjectable[T](Injectable[T]):
|
98
92
|
cls: type[T]
|
99
93
|
|
100
|
-
@override
|
101
94
|
async def aget_instance(self) -> T:
|
102
95
|
return self.get_instance()
|
103
96
|
|
104
|
-
@override
|
105
97
|
def get_instance(self) -> NoReturn:
|
106
98
|
raise InjectionError(f"`{self.cls}` should be an injectable.")
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import asyncio
|
4
|
-
import inspect
|
5
4
|
from abc import ABC, abstractmethod
|
6
5
|
from collections import OrderedDict
|
7
6
|
from collections.abc import (
|
@@ -17,7 +16,8 @@ from contextlib import contextmanager, suppress
|
|
17
16
|
from dataclasses import dataclass, field
|
18
17
|
from enum import StrEnum
|
19
18
|
from functools import partialmethod, singledispatchmethod, update_wrapper
|
20
|
-
from inspect import Signature, isclass, iscoroutinefunction
|
19
|
+
from inspect import Signature, isclass, iscoroutinefunction, markcoroutinefunction
|
20
|
+
from inspect import signature as inspect_signature
|
21
21
|
from logging import Logger, getLogger
|
22
22
|
from queue import Empty, Queue
|
23
23
|
from types import MethodType
|
@@ -29,9 +29,7 @@ from typing import (
|
|
29
29
|
NamedTuple,
|
30
30
|
Protocol,
|
31
31
|
Self,
|
32
|
-
TypeGuard,
|
33
32
|
overload,
|
34
|
-
override,
|
35
33
|
runtime_checkable,
|
36
34
|
)
|
37
35
|
from uuid import uuid4
|
@@ -76,7 +74,6 @@ class LocatorDependenciesUpdated[T](LocatorEvent):
|
|
76
74
|
classes: Collection[InputType[T]]
|
77
75
|
mode: Mode
|
78
76
|
|
79
|
-
@override
|
80
77
|
def __str__(self) -> str:
|
81
78
|
length = len(self.classes)
|
82
79
|
formatted_types = ", ".join(f"`{cls}`" for cls in self.classes)
|
@@ -95,7 +92,6 @@ class ModuleEvent(Event, ABC):
|
|
95
92
|
class ModuleEventProxy(ModuleEvent):
|
96
93
|
event: Event
|
97
94
|
|
98
|
-
@override
|
99
95
|
def __str__(self) -> str:
|
100
96
|
return f"`{self.module}` has propagated an event: {self.origin}"
|
101
97
|
|
@@ -116,7 +112,6 @@ class ModuleAdded(ModuleEvent):
|
|
116
112
|
module_added: Module
|
117
113
|
priority: Priority
|
118
114
|
|
119
|
-
@override
|
120
115
|
def __str__(self) -> str:
|
121
116
|
return f"`{self.module}` now uses `{self.module_added}`."
|
122
117
|
|
@@ -125,7 +120,6 @@ class ModuleAdded(ModuleEvent):
|
|
125
120
|
class ModuleRemoved(ModuleEvent):
|
126
121
|
module_removed: Module
|
127
122
|
|
128
|
-
@override
|
129
123
|
def __str__(self) -> str:
|
130
124
|
return f"`{self.module}` no longer uses `{self.module_removed}`."
|
131
125
|
|
@@ -135,7 +129,6 @@ class ModulePriorityUpdated(ModuleEvent):
|
|
135
129
|
module_updated: Module
|
136
130
|
priority: Priority
|
137
131
|
|
138
|
-
@override
|
139
132
|
def __str__(self) -> str:
|
140
133
|
return (
|
141
134
|
f"In `{self.module}`, the priority `{self.priority}` "
|
@@ -215,18 +208,20 @@ class Updater[T]:
|
|
215
208
|
return Record(injectable, self.mode)
|
216
209
|
|
217
210
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
211
|
+
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
212
|
+
class LocatorHooks[T]:
|
213
|
+
on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool] = field(
|
214
|
+
default_factory=Hook,
|
215
|
+
init=False,
|
216
|
+
)
|
217
|
+
on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]] = field(
|
218
|
+
default_factory=Hook,
|
219
|
+
init=False,
|
220
|
+
)
|
221
|
+
on_update: Hook[[Updater[T]], Updater[T]] = field(
|
222
|
+
default_factory=Hook,
|
223
|
+
init=False,
|
224
|
+
)
|
230
225
|
|
231
226
|
|
232
227
|
@dataclass(repr=False, frozen=True, slots=True)
|
@@ -240,9 +235,8 @@ class Locator(Broker):
|
|
240
235
|
init=False,
|
241
236
|
)
|
242
237
|
|
243
|
-
static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks
|
238
|
+
static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks()
|
244
239
|
|
245
|
-
@override
|
246
240
|
def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
|
247
241
|
for input_class in self.__standardize_inputs((cls,)):
|
248
242
|
try:
|
@@ -254,7 +248,6 @@ class Locator(Broker):
|
|
254
248
|
|
255
249
|
raise NoInjectable(cls)
|
256
250
|
|
257
|
-
@override
|
258
251
|
def __contains__(self, cls: InputType[Any], /) -> bool:
|
259
252
|
return any(
|
260
253
|
input_class in self.__records
|
@@ -262,7 +255,6 @@ class Locator(Broker):
|
|
262
255
|
)
|
263
256
|
|
264
257
|
@property
|
265
|
-
@override
|
266
258
|
def is_locked(self) -> bool:
|
267
259
|
return any(injectable.is_locked for injectable in self.__injectables)
|
268
260
|
|
@@ -284,7 +276,6 @@ class Locator(Broker):
|
|
284
276
|
|
285
277
|
return self
|
286
278
|
|
287
|
-
@override
|
288
279
|
@synchronized()
|
289
280
|
def unlock(self) -> Self:
|
290
281
|
for injectable in self.__injectables:
|
@@ -292,7 +283,6 @@ class Locator(Broker):
|
|
292
283
|
|
293
284
|
return self
|
294
285
|
|
295
|
-
@override
|
296
286
|
async def all_ready(self) -> None:
|
297
287
|
for injectable in self.__injectables:
|
298
288
|
await injectable.aget_instance()
|
@@ -387,7 +377,6 @@ class Module(Broker, EventListener):
|
|
387
377
|
def __post_init__(self) -> None:
|
388
378
|
self.__locator.add_listener(self)
|
389
379
|
|
390
|
-
@override
|
391
380
|
def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
|
392
381
|
for broker in self.__brokers:
|
393
382
|
with suppress(KeyError):
|
@@ -395,12 +384,10 @@ class Module(Broker, EventListener):
|
|
395
384
|
|
396
385
|
raise NoInjectable(cls)
|
397
386
|
|
398
|
-
@override
|
399
387
|
def __contains__(self, cls: InputType[Any], /) -> bool:
|
400
388
|
return any(cls in broker for broker in self.__brokers)
|
401
389
|
|
402
390
|
@property
|
403
|
-
@override
|
404
391
|
def is_locked(self) -> bool:
|
405
392
|
return any(broker.is_locked for broker in self.__brokers)
|
406
393
|
|
@@ -695,7 +682,6 @@ class Module(Broker, EventListener):
|
|
695
682
|
|
696
683
|
return self
|
697
684
|
|
698
|
-
@override
|
699
685
|
@synchronized()
|
700
686
|
def unlock(self) -> Self:
|
701
687
|
for broker in self.__brokers:
|
@@ -703,7 +689,6 @@ class Module(Broker, EventListener):
|
|
703
689
|
|
704
690
|
return self
|
705
691
|
|
706
|
-
@override
|
707
692
|
async def all_ready(self) -> None:
|
708
693
|
for broker in self.__brokers:
|
709
694
|
await broker.all_ready()
|
@@ -720,7 +705,6 @@ class Module(Broker, EventListener):
|
|
720
705
|
self.__channel.remove_listener(listener)
|
721
706
|
return self
|
722
707
|
|
723
|
-
@override
|
724
708
|
def on_event(self, event: Event, /) -> ContextManager[None] | None:
|
725
709
|
self_event = ModuleEventProxy(self, event)
|
726
710
|
return self.dispatch(self_event)
|
@@ -890,7 +874,7 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
|
|
890
874
|
return self.__signature
|
891
875
|
|
892
876
|
with synchronized():
|
893
|
-
signature =
|
877
|
+
signature = inspect_signature(self.wrapped, eval_str=True)
|
894
878
|
self.__signature = signature
|
895
879
|
|
896
880
|
return signature
|
@@ -915,13 +899,11 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
|
|
915
899
|
additional_arguments = self.__dependencies.get_arguments()
|
916
900
|
return self.__bind(args, kwargs, additional_arguments)
|
917
901
|
|
918
|
-
@override
|
919
902
|
async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
920
903
|
self.__setup()
|
921
904
|
arguments = await self.abind(args, kwargs)
|
922
905
|
return self.wrapped(*arguments.args, **arguments.kwargs)
|
923
906
|
|
924
|
-
@override
|
925
907
|
def call(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
926
908
|
self.__setup()
|
927
909
|
arguments = self.bind(args, kwargs)
|
@@ -957,7 +939,6 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
|
|
957
939
|
return decorator(wrapped) if wrapped else decorator
|
958
940
|
|
959
941
|
@singledispatchmethod
|
960
|
-
@override
|
961
942
|
def on_event(self, event: Event, /) -> ContextManager[None] | None: # type: ignore[override]
|
962
943
|
return None
|
963
944
|
|
@@ -1014,11 +995,9 @@ class InjectedFunction[**P, T](ABC):
|
|
1014
995
|
update_wrapper(self, metadata.wrapped)
|
1015
996
|
self.__inject_metadata__ = metadata
|
1016
997
|
|
1017
|
-
@override
|
1018
998
|
def __repr__(self) -> str: # pragma: no cover
|
1019
999
|
return repr(self.__inject_metadata__.wrapped)
|
1020
1000
|
|
1021
|
-
@override
|
1022
1001
|
def __str__(self) -> str: # pragma: no cover
|
1023
1002
|
return str(self.__inject_metadata__.wrapped)
|
1024
1003
|
|
@@ -1043,7 +1022,10 @@ class InjectedFunction[**P, T](ABC):
|
|
1043
1022
|
class AsyncInjectedFunction[**P, T](InjectedFunction[P, Awaitable[T]]):
|
1044
1023
|
__slots__ = ()
|
1045
1024
|
|
1046
|
-
|
1025
|
+
def __init__(self, metadata: InjectMetadata[P, Awaitable[T]]) -> None:
|
1026
|
+
super().__init__(metadata)
|
1027
|
+
markcoroutinefunction(self)
|
1028
|
+
|
1047
1029
|
async def __call__(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
1048
1030
|
return await (await self.__inject_metadata__.acall(*args, **kwargs))
|
1049
1031
|
|
@@ -1051,26 +1033,12 @@ class AsyncInjectedFunction[**P, T](InjectedFunction[P, Awaitable[T]]):
|
|
1051
1033
|
class SyncInjectedFunction[**P, T](InjectedFunction[P, T]):
|
1052
1034
|
__slots__ = ()
|
1053
1035
|
|
1054
|
-
@override
|
1055
1036
|
def __call__(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
1056
1037
|
return self.__inject_metadata__.call(*args, **kwargs)
|
1057
1038
|
|
1058
1039
|
|
1059
|
-
def _is_coroutine_function[**P, T](
|
1060
|
-
function: Callable[P, T] | Callable[P, Awaitable[T]],
|
1061
|
-
) -> TypeGuard[Callable[P, Awaitable[T]]]:
|
1062
|
-
if iscoroutinefunction(function):
|
1063
|
-
return True
|
1064
|
-
|
1065
|
-
elif isclass(function):
|
1066
|
-
return False
|
1067
|
-
|
1068
|
-
call = getattr(function, "__call__", None)
|
1069
|
-
return iscoroutinefunction(call)
|
1070
|
-
|
1071
|
-
|
1072
1040
|
def _get_caller[**P, T](function: Callable[P, T]) -> Caller[P, T]:
|
1073
|
-
if
|
1041
|
+
if iscoroutinefunction(function):
|
1074
1042
|
return AsyncCaller(function)
|
1075
1043
|
|
1076
1044
|
elif isinstance(function, InjectedFunction):
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/__init__.py
RENAMED
File without changes
|
File without changes
|
{python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/threading.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/integrations/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|