python-injection 0.14.2__py3-none-any.whl → 0.14.3__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/_core/__init__.py +0 -53
- injection/_core/module.py +15 -28
- {python_injection-0.14.2.dist-info → python_injection-0.14.3.dist-info}/METADATA +1 -1
- {python_injection-0.14.2.dist-info → python_injection-0.14.3.dist-info}/RECORD +5 -6
- injection/_core/hook.py +0 -106
- {python_injection-0.14.2.dist-info → python_injection-0.14.3.dist-info}/WHEEL +0 -0
injection/_core/__init__.py
CHANGED
@@ -1,53 +0,0 @@
|
|
1
|
-
from collections.abc import Iterable
|
2
|
-
from typing import Any
|
3
|
-
|
4
|
-
from injection._core.common.type import InputType, standardize_types
|
5
|
-
from injection._core.hook import HookGenerator
|
6
|
-
from injection._core.module import Locator, Mode, Record, Updater
|
7
|
-
|
8
|
-
__all__ = ()
|
9
|
-
|
10
|
-
|
11
|
-
@Locator.static_hooks.on_conflict
|
12
|
-
def check_mode[T](
|
13
|
-
new: Record[T],
|
14
|
-
existing: Record[T],
|
15
|
-
cls: InputType[T],
|
16
|
-
*_: Any,
|
17
|
-
**__: Any,
|
18
|
-
) -> HookGenerator[bool]:
|
19
|
-
new_mode = new.mode
|
20
|
-
is_override = new_mode == Mode.OVERRIDE
|
21
|
-
|
22
|
-
if new_mode == existing.mode and not is_override:
|
23
|
-
raise RuntimeError(f"An injectable already exists for the class `{cls}`.")
|
24
|
-
|
25
|
-
value = yield
|
26
|
-
return value or is_override
|
27
|
-
|
28
|
-
|
29
|
-
@Locator.static_hooks.on_conflict
|
30
|
-
def compare_mode_rank[T](
|
31
|
-
new: Record[T],
|
32
|
-
existing: Record[T],
|
33
|
-
*_: Any,
|
34
|
-
**__: Any,
|
35
|
-
) -> HookGenerator[bool]:
|
36
|
-
value = yield
|
37
|
-
return value or new.mode.rank > existing.mode.rank
|
38
|
-
|
39
|
-
|
40
|
-
@Locator.static_hooks.on_input
|
41
|
-
def standardize_input_classes[T](
|
42
|
-
*_: Any,
|
43
|
-
**__: Any,
|
44
|
-
) -> HookGenerator[Iterable[InputType[T]]]:
|
45
|
-
classes = yield
|
46
|
-
return tuple(standardize_types(*classes, with_origin=True))
|
47
|
-
|
48
|
-
|
49
|
-
@Locator.static_hooks.on_update
|
50
|
-
def standardize_classes[T](*_: Any, **__: Any) -> HookGenerator[Updater[T]]:
|
51
|
-
updater = yield
|
52
|
-
updater.classes = frozenset(standardize_types(*updater.classes))
|
53
|
-
return updater
|
injection/_core/module.py
CHANGED
@@ -57,8 +57,8 @@ from injection._core.common.type import (
|
|
57
57
|
TypeInfo,
|
58
58
|
get_return_types,
|
59
59
|
get_yield_hint,
|
60
|
+
standardize_types,
|
60
61
|
)
|
61
|
-
from injection._core.hook import Hook, apply_hooks
|
62
62
|
from injection._core.injectables import (
|
63
63
|
AsyncCMScopedInjectable,
|
64
64
|
CMScopedInjectable,
|
@@ -223,22 +223,6 @@ class Updater[T]:
|
|
223
223
|
return Record(self.injectable, self.mode)
|
224
224
|
|
225
225
|
|
226
|
-
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
227
|
-
class LocatorHooks[T]:
|
228
|
-
on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool] = field(
|
229
|
-
default_factory=Hook,
|
230
|
-
init=False,
|
231
|
-
)
|
232
|
-
on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]] = field(
|
233
|
-
default_factory=Hook,
|
234
|
-
init=False,
|
235
|
-
)
|
236
|
-
on_update: Hook[[Updater[T]], Updater[T]] = field(
|
237
|
-
default_factory=Hook,
|
238
|
-
init=False,
|
239
|
-
)
|
240
|
-
|
241
|
-
|
242
226
|
@dataclass(repr=False, frozen=True, slots=True)
|
243
227
|
class Locator(Broker):
|
244
228
|
__records: dict[InputType[Any], Record[Any]] = field(
|
@@ -250,8 +234,6 @@ class Locator(Broker):
|
|
250
234
|
init=False,
|
251
235
|
)
|
252
236
|
|
253
|
-
static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks()
|
254
|
-
|
255
237
|
def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
|
256
238
|
for input_class in self.__standardize_inputs((cls,)):
|
257
239
|
try:
|
@@ -326,25 +308,30 @@ class Locator(Broker):
|
|
326
308
|
|
327
309
|
yield cls, record
|
328
310
|
|
311
|
+
@staticmethod
|
329
312
|
def __keep_new_record[T](
|
330
|
-
self,
|
331
313
|
new: Record[T],
|
332
314
|
existing: Record[T],
|
333
315
|
cls: InputType[T],
|
334
316
|
) -> bool:
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
317
|
+
new_mode, existing_mode = new.mode, existing.mode
|
318
|
+
is_override = new_mode == Mode.OVERRIDE
|
319
|
+
|
320
|
+
if new_mode == existing_mode and not is_override:
|
321
|
+
raise RuntimeError(f"An injectable already exists for the class `{cls}`.")
|
339
322
|
|
323
|
+
return is_override or new_mode.rank > existing_mode.rank
|
324
|
+
|
325
|
+
@staticmethod
|
340
326
|
def __standardize_inputs[T](
|
341
|
-
self,
|
342
327
|
classes: Iterable[InputType[T]],
|
343
328
|
) -> Iterable[InputType[T]]:
|
344
|
-
return
|
329
|
+
return tuple(standardize_types(*classes, with_origin=True))
|
345
330
|
|
346
|
-
|
347
|
-
|
331
|
+
@staticmethod
|
332
|
+
def __update_preprocessing[T](updater: Updater[T]) -> Updater[T]:
|
333
|
+
updater.classes = frozenset(standardize_types(*updater.classes))
|
334
|
+
return updater
|
348
335
|
|
349
336
|
|
350
337
|
"""
|
@@ -3,11 +3,10 @@ injection/__init__.pyi,sha256=6B5GdRNaAJ15Q-QAL8nNpTBVIKEUPJAwWIlCSjOkkJ8,10058
|
|
3
3
|
injection/exceptions.py,sha256=dp9XYpWHh8R76wbWDJdjmpTHGQp8KuCeveTqarXY_6Y,999
|
4
4
|
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
injection/utils.py,sha256=Lr0qHaq3_1AkUoAaw2XmMNie_alwYTeTrRlO22FeCnk,2762
|
6
|
-
injection/_core/__init__.py,sha256=
|
6
|
+
injection/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
injection/_core/descriptors.py,sha256=7fSHlgAqmgR_Uta8KocBapOt1Xyj2dI7RY9ZdoStTzw,726
|
8
|
-
injection/_core/hook.py,sha256=rJyaSwFAHM8qizWANPUSt5KzWdjxc5oJ2U8hcGeZjU8,3097
|
9
8
|
injection/_core/injectables.py,sha256=GIumNp0TXf8Voxe1sCPhcqq2gyw4E_hl7I45IJ_tyHE,4512
|
10
|
-
injection/_core/module.py,sha256=
|
9
|
+
injection/_core/module.py,sha256=pIAolGgvBLGcYxxrS3kyVwCsfeRelIFbjXe-Se3dW8g,30884
|
11
10
|
injection/_core/scope.py,sha256=pwOqVKOUM_ZteNScgp-hLqyOHg5Ew75jWlfWLLD2PU8,5437
|
12
11
|
injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
12
|
injection/_core/common/asynchronous.py,sha256=9bQDVRE6eqo9K0d5H9RzyFalf0WGoGP7cDrKDGbvZPI,1500
|
@@ -20,6 +19,6 @@ injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
20
19
|
injection/integrations/fastapi.py,sha256=YHSs85_3m6TUVtOwUcV157b3UZJQIw_aXWAg199a-YE,594
|
21
20
|
injection/testing/__init__.py,sha256=Bh3JqEXw62-JnUnspOXr2jpjGXZJ_K_K9CgfD7dPZeQ,793
|
22
21
|
injection/testing/__init__.pyi,sha256=1h9zNGghxlo4D1jAx5s8EHk54mn7o-qO7WgJa6hwX6U,484
|
23
|
-
python_injection-0.14.
|
24
|
-
python_injection-0.14.
|
25
|
-
python_injection-0.14.
|
22
|
+
python_injection-0.14.3.dist-info/METADATA,sha256=ZqqveCnqOcvOBf-l8Zvu3NztDTu6QYPRHeHVUel71TE,3199
|
23
|
+
python_injection-0.14.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
24
|
+
python_injection-0.14.3.dist-info/RECORD,,
|
injection/_core/hook.py
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
import itertools
|
2
|
-
from collections.abc import Callable, Generator, Iterator
|
3
|
-
from dataclasses import dataclass, field
|
4
|
-
from inspect import isclass, isgeneratorfunction
|
5
|
-
from typing import Any, Self, TypeGuard
|
6
|
-
|
7
|
-
from injection.exceptions import HookError
|
8
|
-
|
9
|
-
type HookGenerator[T] = Generator[None, T, T]
|
10
|
-
type HookGeneratorFunction[**P, T] = Callable[P, HookGenerator[T]]
|
11
|
-
type HookFunction[**P, T] = Callable[P, T] | HookGeneratorFunction[P, T]
|
12
|
-
|
13
|
-
|
14
|
-
@dataclass(eq=False, frozen=True, slots=True)
|
15
|
-
class Hook[**P, T]:
|
16
|
-
__functions: list[HookFunction[P, T]] = field(
|
17
|
-
default_factory=list,
|
18
|
-
init=False,
|
19
|
-
repr=False,
|
20
|
-
)
|
21
|
-
|
22
|
-
def __call__(
|
23
|
-
self,
|
24
|
-
wrapped: HookFunction[P, T] | type[HookFunction[P, T]] | None = None,
|
25
|
-
/,
|
26
|
-
) -> Any:
|
27
|
-
def decorator(wp: Any) -> Any:
|
28
|
-
self.add(wp() if isclass(wp) else wp)
|
29
|
-
return wp
|
30
|
-
|
31
|
-
return decorator(wrapped) if wrapped else decorator
|
32
|
-
|
33
|
-
@property
|
34
|
-
def __stack(self) -> Iterator[HookFunction[P, T]]:
|
35
|
-
return iter(self.__functions)
|
36
|
-
|
37
|
-
def add(self, *functions: HookFunction[P, T]) -> Self:
|
38
|
-
self.__functions.extend(reversed(functions))
|
39
|
-
return self
|
40
|
-
|
41
|
-
@classmethod
|
42
|
-
def apply_several(cls, handler: Callable[P, T], *hooks: Self) -> Callable[P, T]:
|
43
|
-
stack = itertools.chain.from_iterable((hook.__stack for hook in hooks))
|
44
|
-
return cls.__apply_stack(handler, stack)
|
45
|
-
|
46
|
-
@classmethod
|
47
|
-
def __apply_function(
|
48
|
-
cls,
|
49
|
-
handler: Callable[P, T],
|
50
|
-
function: HookFunction[P, T],
|
51
|
-
) -> Callable[P, T]:
|
52
|
-
if not cls.__is_hook_generator_function(function):
|
53
|
-
return function # type: ignore[return-value]
|
54
|
-
|
55
|
-
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
56
|
-
hook: HookGenerator[T] = function(*args, **kwargs)
|
57
|
-
|
58
|
-
try:
|
59
|
-
next(hook)
|
60
|
-
|
61
|
-
try:
|
62
|
-
value = handler(*args, **kwargs)
|
63
|
-
except BaseException as exc:
|
64
|
-
hook.throw(exc)
|
65
|
-
else:
|
66
|
-
hook.send(value)
|
67
|
-
|
68
|
-
except StopIteration as stop:
|
69
|
-
return stop.value
|
70
|
-
|
71
|
-
finally:
|
72
|
-
hook.close()
|
73
|
-
|
74
|
-
raise HookError("Missing return value.")
|
75
|
-
|
76
|
-
return wrapper
|
77
|
-
|
78
|
-
@classmethod
|
79
|
-
def __apply_stack(
|
80
|
-
cls,
|
81
|
-
handler: Callable[P, T],
|
82
|
-
stack: Iterator[HookFunction[P, T]],
|
83
|
-
) -> Callable[P, T]:
|
84
|
-
for function in stack:
|
85
|
-
new_handler = cls.__apply_function(handler, function)
|
86
|
-
return cls.__apply_stack(new_handler, stack)
|
87
|
-
|
88
|
-
return handler
|
89
|
-
|
90
|
-
@staticmethod
|
91
|
-
def __is_hook_generator_function[**_P, _T](
|
92
|
-
function: HookFunction[_P, _T],
|
93
|
-
) -> TypeGuard[HookGeneratorFunction[_P, _T]]:
|
94
|
-
for fn in function, getattr(function, "__call__", None):
|
95
|
-
if isgeneratorfunction(fn):
|
96
|
-
return True
|
97
|
-
|
98
|
-
return False
|
99
|
-
|
100
|
-
|
101
|
-
def apply_hooks[**P, T](
|
102
|
-
handler: Callable[P, T],
|
103
|
-
hook: Hook[P, T],
|
104
|
-
*hooks: Hook[P, T],
|
105
|
-
) -> Callable[P, T]:
|
106
|
-
return Hook.apply_several(handler, hook, *hooks)
|
File without changes
|