python-injection 0.9.5__py3-none-any.whl → 0.9.7__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.
Potentially problematic release.
This version of python-injection might be problematic. Click here for more details.
- injection/__init__.py +5 -3
- injection/__init__.pyi +34 -17
- injection/{common → _core/common}/lazy.py +1 -1
- injection/{common/tools → _core/common}/threading.py +2 -1
- injection/{common/tools → _core/common}/type.py +7 -2
- injection/{core → _core}/module.py +77 -42
- injection/testing/__init__.py +5 -2
- injection/testing/__init__.pyi +1 -0
- injection/utils.py +8 -8
- {python_injection-0.9.5.dist-info → python_injection-0.9.7.dist-info}/METADATA +28 -1
- python_injection-0.9.7.dist-info/RECORD +20 -0
- injection/common/tools/__init__.py +0 -0
- python_injection-0.9.5.dist-info/RECORD +0 -21
- /injection/{core → _core}/__init__.py +0 -0
- /injection/{common → _core/common}/__init__.py +0 -0
- /injection/{common → _core/common}/event.py +0 -0
- /injection/{common → _core/common}/invertible.py +0 -0
- {python_injection-0.9.5.dist-info → python_injection-0.9.7.dist-info}/WHEEL +0 -0
injection/__init__.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
from .
|
|
2
|
-
from .
|
|
3
|
-
from .
|
|
1
|
+
from ._core import Injectable, Module
|
|
2
|
+
from ._core import Mode as InjectableMode
|
|
3
|
+
from ._core import Priority as ModulePriority
|
|
4
4
|
|
|
5
5
|
__all__ = (
|
|
6
6
|
"Injectable",
|
|
7
7
|
"InjectableMode",
|
|
8
8
|
"Module",
|
|
9
9
|
"ModulePriority",
|
|
10
|
+
"constant",
|
|
10
11
|
"find_instance",
|
|
11
12
|
"get_instance",
|
|
12
13
|
"get_lazy_instance",
|
|
@@ -26,6 +27,7 @@ def mod(name: str = None, /) -> Module:
|
|
|
26
27
|
return Module.from_name(name)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
constant = mod().constant
|
|
29
31
|
find_instance = mod().find_instance
|
|
30
32
|
get_instance = mod().get_instance
|
|
31
33
|
get_lazy_instance = mod().get_lazy_instance
|
injection/__init__.pyi
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from contextlib import ContextDecorator
|
|
4
|
-
from enum import
|
|
4
|
+
from enum import Enum
|
|
5
5
|
from logging import Logger
|
|
6
6
|
from types import UnionType
|
|
7
7
|
from typing import (
|
|
@@ -9,18 +9,20 @@ from typing import (
|
|
|
9
9
|
ContextManager,
|
|
10
10
|
Protocol,
|
|
11
11
|
Self,
|
|
12
|
+
TypeAliasType,
|
|
12
13
|
final,
|
|
13
14
|
runtime_checkable,
|
|
14
15
|
)
|
|
15
16
|
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
17
|
+
from ._core import InjectableFactory as _InjectableFactory
|
|
18
|
+
from ._core import ModeStr as InjectableModeStr
|
|
19
|
+
from ._core import PriorityStr as ModulePriorityStr
|
|
20
|
+
from ._core.common.invertible import Invertible as _Invertible
|
|
21
|
+
from ._core.common.type import TypeInfo as _TypeInfo
|
|
21
22
|
|
|
22
23
|
_: Module = ...
|
|
23
24
|
|
|
25
|
+
constant = _.constant
|
|
24
26
|
find_instance = _.find_instance
|
|
25
27
|
get_instance = _.get_instance
|
|
26
28
|
get_lazy_instance = _.get_lazy_instance
|
|
@@ -47,7 +49,7 @@ class Module:
|
|
|
47
49
|
"""
|
|
48
50
|
|
|
49
51
|
def __init__(self, name: str = ...): ...
|
|
50
|
-
def __contains__(self, cls: type | UnionType, /) -> bool: ...
|
|
52
|
+
def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool: ...
|
|
51
53
|
@property
|
|
52
54
|
def is_locked(self) -> bool: ...
|
|
53
55
|
def inject(self, wrapped: Callable[..., Any] = ..., /):
|
|
@@ -62,9 +64,9 @@ class Module:
|
|
|
62
64
|
wrapped: Callable[..., T] = ...,
|
|
63
65
|
/,
|
|
64
66
|
*,
|
|
65
|
-
cls:
|
|
67
|
+
cls: _InjectableFactory[T] = ...,
|
|
66
68
|
inject: bool = ...,
|
|
67
|
-
on:
|
|
69
|
+
on: _TypeInfo[T] = ...,
|
|
68
70
|
mode: InjectableMode | InjectableModeStr = ...,
|
|
69
71
|
):
|
|
70
72
|
"""
|
|
@@ -79,7 +81,7 @@ class Module:
|
|
|
79
81
|
/,
|
|
80
82
|
*,
|
|
81
83
|
inject: bool = ...,
|
|
82
|
-
on:
|
|
84
|
+
on: _TypeInfo[T] = ...,
|
|
83
85
|
mode: InjectableMode | InjectableModeStr = ...,
|
|
84
86
|
):
|
|
85
87
|
"""
|
|
@@ -95,11 +97,26 @@ class Module:
|
|
|
95
97
|
registered.
|
|
96
98
|
"""
|
|
97
99
|
|
|
100
|
+
def constant[T](
|
|
101
|
+
self,
|
|
102
|
+
wrapped: Callable[..., T] = ...,
|
|
103
|
+
/,
|
|
104
|
+
*,
|
|
105
|
+
on: _TypeInfo[T] = ...,
|
|
106
|
+
mode: InjectableMode | InjectableModeStr = ...,
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Decorator applicable to a class or function. It is used to indicate how the
|
|
110
|
+
constant is constructed. At injection time, the injected instance will always
|
|
111
|
+
be the same. Unlike `@singleton`, dependencies will not be resolved.
|
|
112
|
+
"""
|
|
113
|
+
|
|
98
114
|
def set_constant[T](
|
|
99
115
|
self,
|
|
100
116
|
instance: T,
|
|
101
|
-
on:
|
|
117
|
+
on: _TypeInfo[T] = ...,
|
|
102
118
|
*,
|
|
119
|
+
alias: bool = ...,
|
|
103
120
|
mode: InjectableMode | InjectableModeStr = ...,
|
|
104
121
|
) -> Self:
|
|
105
122
|
"""
|
|
@@ -108,13 +125,13 @@ class Module:
|
|
|
108
125
|
that no dependencies are resolved, so the module doesn't need to be locked.
|
|
109
126
|
"""
|
|
110
127
|
|
|
111
|
-
def find_instance[T](self, cls: type[T]) -> T:
|
|
128
|
+
def find_instance[T](self, cls: type[T] | TypeAliasType) -> T:
|
|
112
129
|
"""
|
|
113
130
|
Function used to retrieve an instance associated with the type passed in
|
|
114
131
|
parameter or an exception will be raised.
|
|
115
132
|
"""
|
|
116
133
|
|
|
117
|
-
def get_instance[T](self, cls: type[T]) -> T | None:
|
|
134
|
+
def get_instance[T](self, cls: type[T] | TypeAliasType) -> T | None:
|
|
118
135
|
"""
|
|
119
136
|
Function used to retrieve an instance associated with the type passed in
|
|
120
137
|
parameter or return `None`.
|
|
@@ -122,10 +139,10 @@ class Module:
|
|
|
122
139
|
|
|
123
140
|
def get_lazy_instance[T](
|
|
124
141
|
self,
|
|
125
|
-
cls: type[T],
|
|
142
|
+
cls: type[T] | TypeAliasType,
|
|
126
143
|
*,
|
|
127
144
|
cache: bool = ...,
|
|
128
|
-
) ->
|
|
145
|
+
) -> _Invertible[T | None]:
|
|
129
146
|
"""
|
|
130
147
|
Function used to retrieve an instance associated with the type passed in
|
|
131
148
|
parameter or `None`. Return a `Invertible` object. To access the instance
|
|
@@ -199,7 +216,7 @@ class Module:
|
|
|
199
216
|
"""
|
|
200
217
|
|
|
201
218
|
@final
|
|
202
|
-
class ModulePriority(
|
|
219
|
+
class ModulePriority(Enum):
|
|
203
220
|
LOW = ...
|
|
204
221
|
HIGH = ...
|
|
205
222
|
|
|
@@ -212,7 +229,7 @@ class Injectable[T](Protocol):
|
|
|
212
229
|
def get_instance(self) -> T: ...
|
|
213
230
|
|
|
214
231
|
@final
|
|
215
|
-
class InjectableMode(
|
|
232
|
+
class InjectableMode(Enum):
|
|
216
233
|
FALLBACK = ...
|
|
217
234
|
NORMAL = ...
|
|
218
235
|
OVERRIDE = ...
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections.abc import Iterator
|
|
1
2
|
from contextlib import contextmanager
|
|
2
3
|
from threading import RLock
|
|
3
4
|
|
|
@@ -5,7 +6,7 @@ __all__ = ("synchronized",)
|
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
@contextmanager
|
|
8
|
-
def synchronized():
|
|
9
|
+
def synchronized() -> Iterator[RLock]:
|
|
9
10
|
lock = RLock()
|
|
10
11
|
|
|
11
12
|
with lock:
|
|
@@ -6,6 +6,7 @@ from typing import (
|
|
|
6
6
|
Any,
|
|
7
7
|
NamedTuple,
|
|
8
8
|
Self,
|
|
9
|
+
TypeAliasType,
|
|
9
10
|
Union,
|
|
10
11
|
get_args,
|
|
11
12
|
get_origin,
|
|
@@ -13,7 +14,9 @@ from typing import (
|
|
|
13
14
|
|
|
14
15
|
__all__ = ("TypeInfo", "TypeReport", "analyze_types", "get_return_types")
|
|
15
16
|
|
|
16
|
-
type TypeInfo[T] =
|
|
17
|
+
type TypeInfo[T] = (
|
|
18
|
+
type[T] | Callable[..., T] | Iterable[TypeInfo[T]] | UnionType | TypeAliasType
|
|
19
|
+
)
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class TypeReport[T](NamedTuple):
|
|
@@ -57,7 +60,9 @@ def analyze_types(*types: type | Any) -> Iterator[TypeReport[Any]]:
|
|
|
57
60
|
yield from analyze_types(*inner_types)
|
|
58
61
|
|
|
59
62
|
|
|
60
|
-
def get_return_types(
|
|
63
|
+
def get_return_types(
|
|
64
|
+
*args: TypeInfo[Any],
|
|
65
|
+
) -> Iterator[type | UnionType | TypeAliasType]:
|
|
61
66
|
for arg in args:
|
|
62
67
|
if isinstance(arg, Iterable) and not (
|
|
63
68
|
isinstance(arg, type | str) or isinstance(get_origin(arg), type)
|
|
@@ -28,14 +28,16 @@ from typing import (
|
|
|
28
28
|
NoReturn,
|
|
29
29
|
Protocol,
|
|
30
30
|
Self,
|
|
31
|
+
TypeAliasType,
|
|
31
32
|
runtime_checkable,
|
|
32
33
|
)
|
|
34
|
+
from uuid import uuid4
|
|
33
35
|
|
|
34
|
-
from injection.common.event import Event, EventChannel, EventListener
|
|
35
|
-
from injection.common.invertible import Invertible, SimpleInvertible
|
|
36
|
-
from injection.common.lazy import Lazy, LazyMapping
|
|
37
|
-
from injection.common.
|
|
38
|
-
from injection.common.
|
|
36
|
+
from injection._core.common.event import Event, EventChannel, EventListener
|
|
37
|
+
from injection._core.common.invertible import Invertible, SimpleInvertible
|
|
38
|
+
from injection._core.common.lazy import Lazy, LazyMapping
|
|
39
|
+
from injection._core.common.threading import synchronized
|
|
40
|
+
from injection._core.common.type import (
|
|
39
41
|
TypeInfo,
|
|
40
42
|
TypeReport,
|
|
41
43
|
analyze_types,
|
|
@@ -65,12 +67,12 @@ Events
|
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
@dataclass(frozen=True, slots=True)
|
|
68
|
-
class
|
|
69
|
-
|
|
70
|
+
class LocatorEvent(Event, ABC):
|
|
71
|
+
locator: Locator
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
@dataclass(frozen=True, slots=True)
|
|
73
|
-
class
|
|
75
|
+
class LocatorDependenciesUpdated(LocatorEvent):
|
|
74
76
|
reports: Collection[TypeReport]
|
|
75
77
|
mode: Mode
|
|
76
78
|
|
|
@@ -78,8 +80,8 @@ class ContainerDependenciesUpdated(ContainerEvent):
|
|
|
78
80
|
length = len(self.reports)
|
|
79
81
|
formatted_types = ", ".join(f"`{report.type}`" for report in self.reports)
|
|
80
82
|
return (
|
|
81
|
-
f"{length}
|
|
82
|
-
f"
|
|
83
|
+
f"{length} dependenc{"ies" if length > 1 else "y"} have been "
|
|
84
|
+
f"updated{f": {formatted_types}" if formatted_types else ""}."
|
|
83
85
|
)
|
|
84
86
|
|
|
85
87
|
|
|
@@ -214,11 +216,15 @@ class Broker(Protocol):
|
|
|
214
216
|
__slots__ = ()
|
|
215
217
|
|
|
216
218
|
@abstractmethod
|
|
217
|
-
def __getitem__[T](
|
|
219
|
+
def __getitem__[T](
|
|
220
|
+
self,
|
|
221
|
+
cls: type[T] | UnionType | TypeAliasType,
|
|
222
|
+
/,
|
|
223
|
+
) -> Injectable[T]:
|
|
218
224
|
raise NotImplementedError
|
|
219
225
|
|
|
220
226
|
@abstractmethod
|
|
221
|
-
def __contains__(self, cls: type | UnionType, /) -> bool:
|
|
227
|
+
def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
|
|
222
228
|
raise NotImplementedError
|
|
223
229
|
|
|
224
230
|
@property
|
|
@@ -232,7 +238,7 @@ class Broker(Protocol):
|
|
|
232
238
|
|
|
233
239
|
|
|
234
240
|
"""
|
|
235
|
-
|
|
241
|
+
Locator
|
|
236
242
|
"""
|
|
237
243
|
|
|
238
244
|
|
|
@@ -259,11 +265,15 @@ class Record[T](NamedTuple):
|
|
|
259
265
|
|
|
260
266
|
|
|
261
267
|
@dataclass(repr=False, frozen=True, slots=True)
|
|
262
|
-
class
|
|
268
|
+
class Locator(Broker):
|
|
263
269
|
__records: dict[TypeReport, Record] = field(default_factory=dict, init=False)
|
|
264
270
|
__channel: EventChannel = field(default_factory=EventChannel, init=False)
|
|
265
271
|
|
|
266
|
-
def __getitem__[T](
|
|
272
|
+
def __getitem__[T](
|
|
273
|
+
self,
|
|
274
|
+
cls: type[T] | UnionType | TypeAliasType,
|
|
275
|
+
/,
|
|
276
|
+
) -> Injectable[T]:
|
|
267
277
|
for report in analyze_types(cls):
|
|
268
278
|
for scoped_report in OrderedDict.fromkeys((report, report.no_args)):
|
|
269
279
|
try:
|
|
@@ -275,7 +285,7 @@ class Container(Broker):
|
|
|
275
285
|
|
|
276
286
|
raise NoInjectable(cls)
|
|
277
287
|
|
|
278
|
-
def __contains__(self, cls: type | UnionType, /) -> bool:
|
|
288
|
+
def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
|
|
279
289
|
return any(report in self.__records for report in analyze_types(cls))
|
|
280
290
|
|
|
281
291
|
@property
|
|
@@ -289,18 +299,19 @@ class Container(Broker):
|
|
|
289
299
|
@synchronized()
|
|
290
300
|
def update[T](
|
|
291
301
|
self,
|
|
292
|
-
classes: Iterable[type[T] | UnionType],
|
|
302
|
+
classes: Iterable[type[T] | UnionType | TypeAliasType],
|
|
293
303
|
injectable: Injectable[T],
|
|
294
304
|
mode: Mode | ModeStr,
|
|
295
305
|
) -> Self:
|
|
296
306
|
mode = Mode(mode)
|
|
307
|
+
record = Record(injectable, mode)
|
|
297
308
|
records = {
|
|
298
|
-
report:
|
|
309
|
+
report: record
|
|
299
310
|
for report in self.__prepare_reports_for_updating(classes, mode)
|
|
300
311
|
}
|
|
301
312
|
|
|
302
313
|
if records:
|
|
303
|
-
event =
|
|
314
|
+
event = LocatorDependenciesUpdated(self, records.keys(), mode)
|
|
304
315
|
|
|
305
316
|
with self.dispatch(event):
|
|
306
317
|
self.__records.update(records)
|
|
@@ -323,7 +334,7 @@ class Container(Broker):
|
|
|
323
334
|
|
|
324
335
|
def __prepare_reports_for_updating(
|
|
325
336
|
self,
|
|
326
|
-
classes: Iterable[type | UnionType],
|
|
337
|
+
classes: Iterable[type | UnionType | TypeAliasType],
|
|
327
338
|
mode: Mode,
|
|
328
339
|
) -> Iterator[TypeReport]:
|
|
329
340
|
rank = mode.rank
|
|
@@ -367,25 +378,25 @@ type InjectableFactory[T] = Callable[[Callable[..., T]], Injectable[T]]
|
|
|
367
378
|
|
|
368
379
|
|
|
369
380
|
@dataclass(eq=False, frozen=True, slots=True)
|
|
370
|
-
class Module(
|
|
371
|
-
name: str
|
|
381
|
+
class Module(Broker, EventListener):
|
|
382
|
+
name: str = field(default_factory=lambda: f"anonymous@{uuid4().hex[:7]}")
|
|
372
383
|
__channel: EventChannel = field(
|
|
373
384
|
default_factory=EventChannel,
|
|
374
385
|
init=False,
|
|
375
386
|
repr=False,
|
|
376
387
|
)
|
|
377
|
-
|
|
378
|
-
default_factory=
|
|
388
|
+
__locator: Locator = field(
|
|
389
|
+
default_factory=Locator,
|
|
379
390
|
init=False,
|
|
380
391
|
repr=False,
|
|
381
392
|
)
|
|
382
|
-
|
|
383
|
-
default_factory=
|
|
393
|
+
__loggers: list[Logger] = field(
|
|
394
|
+
default_factory=lambda: [getLogger(__name__)],
|
|
384
395
|
init=False,
|
|
385
396
|
repr=False,
|
|
386
397
|
)
|
|
387
|
-
|
|
388
|
-
default_factory=
|
|
398
|
+
__modules: OrderedDict[Module, None] = field(
|
|
399
|
+
default_factory=OrderedDict,
|
|
389
400
|
init=False,
|
|
390
401
|
repr=False,
|
|
391
402
|
)
|
|
@@ -393,19 +404,20 @@ class Module(EventListener, Broker):
|
|
|
393
404
|
__instances: ClassVar[dict[str, Module]] = {}
|
|
394
405
|
|
|
395
406
|
def __post_init__(self):
|
|
396
|
-
self.
|
|
407
|
+
self.__locator.add_listener(self)
|
|
397
408
|
|
|
398
|
-
def __getitem__[T](
|
|
409
|
+
def __getitem__[T](
|
|
410
|
+
self,
|
|
411
|
+
cls: type[T] | UnionType | TypeAliasType,
|
|
412
|
+
/,
|
|
413
|
+
) -> Injectable[T]:
|
|
399
414
|
for broker in self.__brokers:
|
|
400
415
|
with suppress(KeyError):
|
|
401
416
|
return broker[cls]
|
|
402
417
|
|
|
403
418
|
raise NoInjectable(cls)
|
|
404
419
|
|
|
405
|
-
def
|
|
406
|
-
self.update((cls,), injectable)
|
|
407
|
-
|
|
408
|
-
def __contains__(self, cls: type | UnionType, /) -> bool:
|
|
420
|
+
def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
|
|
409
421
|
return any(cls in broker for broker in self.__brokers)
|
|
410
422
|
|
|
411
423
|
@property
|
|
@@ -415,7 +427,7 @@ class Module(EventListener, Broker):
|
|
|
415
427
|
@property
|
|
416
428
|
def __brokers(self) -> Iterator[Broker]:
|
|
417
429
|
yield from tuple(self.__modules)
|
|
418
|
-
yield self.
|
|
430
|
+
yield self.__locator
|
|
419
431
|
|
|
420
432
|
def injectable[T](
|
|
421
433
|
self,
|
|
@@ -449,18 +461,41 @@ class Module(EventListener, Broker):
|
|
|
449
461
|
|
|
450
462
|
return decorator(wrapped) if wrapped else decorator
|
|
451
463
|
|
|
464
|
+
def constant[T](
|
|
465
|
+
self,
|
|
466
|
+
wrapped: Callable[..., T] = None,
|
|
467
|
+
/,
|
|
468
|
+
*,
|
|
469
|
+
on: TypeInfo[T] = (),
|
|
470
|
+
mode: Mode | ModeStr = Mode.get_default(),
|
|
471
|
+
):
|
|
472
|
+
def decorator(wp):
|
|
473
|
+
instance = wp()
|
|
474
|
+
self.set_constant(
|
|
475
|
+
instance,
|
|
476
|
+
on=on,
|
|
477
|
+
mode=mode,
|
|
478
|
+
)
|
|
479
|
+
return wp
|
|
480
|
+
|
|
481
|
+
return decorator(wrapped) if wrapped else decorator
|
|
482
|
+
|
|
452
483
|
def set_constant[T](
|
|
453
484
|
self,
|
|
454
485
|
instance: T,
|
|
455
486
|
on: TypeInfo[T] = (),
|
|
456
487
|
*,
|
|
488
|
+
alias: bool = False,
|
|
457
489
|
mode: Mode | ModeStr = Mode.get_default(),
|
|
458
490
|
) -> Self:
|
|
459
|
-
|
|
491
|
+
if not alias:
|
|
492
|
+
cls = type(instance)
|
|
493
|
+
on = (cls, on)
|
|
494
|
+
|
|
460
495
|
self.injectable(
|
|
461
496
|
lambda: instance,
|
|
462
497
|
inject=False,
|
|
463
|
-
on=
|
|
498
|
+
on=on,
|
|
464
499
|
mode=mode,
|
|
465
500
|
)
|
|
466
501
|
return self
|
|
@@ -488,11 +523,11 @@ class Module(EventListener, Broker):
|
|
|
488
523
|
|
|
489
524
|
return decorator(wrapped) if wrapped else decorator
|
|
490
525
|
|
|
491
|
-
def find_instance[T](self, cls: type[T]) -> T:
|
|
526
|
+
def find_instance[T](self, cls: type[T] | TypeAliasType) -> T:
|
|
492
527
|
injectable = self[cls]
|
|
493
528
|
return injectable.get_instance()
|
|
494
529
|
|
|
495
|
-
def get_instance[T](self, cls: type[T]) -> T | None:
|
|
530
|
+
def get_instance[T](self, cls: type[T] | TypeAliasType) -> T | None:
|
|
496
531
|
try:
|
|
497
532
|
return self.find_instance(cls)
|
|
498
533
|
except KeyError:
|
|
@@ -500,7 +535,7 @@ class Module(EventListener, Broker):
|
|
|
500
535
|
|
|
501
536
|
def get_lazy_instance[T](
|
|
502
537
|
self,
|
|
503
|
-
cls: type[T],
|
|
538
|
+
cls: type[T] | TypeAliasType,
|
|
504
539
|
*,
|
|
505
540
|
cache: bool = False,
|
|
506
541
|
) -> Invertible[T | None]:
|
|
@@ -513,11 +548,11 @@ class Module(EventListener, Broker):
|
|
|
513
548
|
|
|
514
549
|
def update[T](
|
|
515
550
|
self,
|
|
516
|
-
classes: Iterable[type[T] | UnionType],
|
|
551
|
+
classes: Iterable[type[T] | UnionType | TypeAliasType],
|
|
517
552
|
injectable: Injectable[T],
|
|
518
553
|
mode: Mode | ModeStr = Mode.get_default(),
|
|
519
554
|
) -> Self:
|
|
520
|
-
self.
|
|
555
|
+
self.__locator.update(classes, injectable, mode)
|
|
521
556
|
return self
|
|
522
557
|
|
|
523
558
|
def init_modules(self, *modules: Module) -> Self:
|
injection/testing/__init__.py
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
from contextlib import contextmanager
|
|
2
|
-
from functools import partial
|
|
3
2
|
|
|
4
3
|
from injection import Module, ModulePriority, mod
|
|
5
4
|
|
|
6
5
|
__all__ = (
|
|
7
6
|
"set_test_constant",
|
|
8
7
|
"should_be_test_injectable",
|
|
8
|
+
"test_constant",
|
|
9
9
|
"test_injectable",
|
|
10
10
|
"test_singleton",
|
|
11
11
|
"use_test_injectables",
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
tmod
|
|
15
|
+
def tmod() -> Module:
|
|
16
|
+
return mod("testing")
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
set_test_constant = tmod().set_constant
|
|
18
20
|
should_be_test_injectable = tmod().should_be_injectable
|
|
21
|
+
test_constant = tmod().constant
|
|
19
22
|
test_injectable = tmod().injectable
|
|
20
23
|
test_singleton = tmod().singleton
|
|
21
24
|
|
injection/testing/__init__.pyi
CHANGED
injection/utils.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
from collections.abc import Callable, Iterator
|
|
2
2
|
from importlib import import_module
|
|
3
3
|
from pkgutil import walk_packages
|
|
4
|
-
from types import ModuleType
|
|
4
|
+
from types import ModuleType as PythonModule
|
|
5
5
|
|
|
6
6
|
__all__ = ("load_package",)
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def load_package(
|
|
10
|
-
package:
|
|
10
|
+
package: PythonModule | str,
|
|
11
11
|
predicate: Callable[[str], bool] = lambda module_name: True,
|
|
12
|
-
) ->
|
|
12
|
+
) -> dict[str, PythonModule]:
|
|
13
13
|
"""
|
|
14
14
|
Function for importing all modules in a Python package.
|
|
15
15
|
Pass the `predicate` parameter if you want to filter the modules to be imported.
|
|
@@ -18,13 +18,13 @@ def load_package(
|
|
|
18
18
|
if isinstance(package, str):
|
|
19
19
|
package = import_module(package)
|
|
20
20
|
|
|
21
|
-
return
|
|
21
|
+
return dict(__iter_modules_from(package, predicate))
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def
|
|
25
|
-
package:
|
|
24
|
+
def __iter_modules_from(
|
|
25
|
+
package: PythonModule,
|
|
26
26
|
predicate: Callable[[str], bool],
|
|
27
|
-
) -> Iterator[
|
|
27
|
+
) -> Iterator[tuple[str, PythonModule]]:
|
|
28
28
|
try:
|
|
29
29
|
path = package.__path__
|
|
30
30
|
except AttributeError as exc:
|
|
@@ -38,4 +38,4 @@ def __iter_modules(
|
|
|
38
38
|
if info.ispkg or not predicate(name):
|
|
39
39
|
continue
|
|
40
40
|
|
|
41
|
-
yield import_module(name)
|
|
41
|
+
yield name, import_module(name)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-injection
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.7
|
|
4
4
|
Summary: Fast and easy dependency injection framework.
|
|
5
5
|
Home-page: https://github.com/100nm/python-injection
|
|
6
6
|
License: MIT
|
|
@@ -63,6 +63,18 @@ service_c = ServiceC()
|
|
|
63
63
|
set_constant(service_c)
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
Or here is the decorator `constant` which is equivalent:
|
|
67
|
+
|
|
68
|
+
> Unlike `@singleton`, dependencies will not be resolved.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from injection import constant
|
|
72
|
+
|
|
73
|
+
@constant
|
|
74
|
+
class ServiceC:
|
|
75
|
+
""" class implementation """
|
|
76
|
+
```
|
|
77
|
+
|
|
66
78
|
## Inject an instance
|
|
67
79
|
|
|
68
80
|
To inject one or several instances, use `inject` decorator.
|
|
@@ -173,3 +185,18 @@ def service_d_recipe() -> ServiceD:
|
|
|
173
185
|
""" recipe implementation """
|
|
174
186
|
```
|
|
175
187
|
|
|
188
|
+
## Working with type aliases
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from injection import injectable, set_constant
|
|
192
|
+
|
|
193
|
+
type APIKey = str
|
|
194
|
+
|
|
195
|
+
set_constant("<secret_api_key>", APIKey, alias=True)
|
|
196
|
+
|
|
197
|
+
@injectable
|
|
198
|
+
class Client:
|
|
199
|
+
def __init__(self, api_key: APIKey):
|
|
200
|
+
...
|
|
201
|
+
```
|
|
202
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
injection/__init__.py,sha256=5Hv4Qg9cQIa8pOnQtnmOOUwIGMaXzUpbM1uYuN18VyI,843
|
|
2
|
+
injection/__init__.pyi,sha256=J1egEioa3t5cdTIySgPwPGfs5STGK--d9shs-9nfzsg,7051
|
|
3
|
+
injection/_core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
|
|
4
|
+
injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
injection/_core/common/event.py,sha256=5Rdb2m3vAMCic8cQAVkStJDbrDrW_lk6kav8wYwmexM,1283
|
|
6
|
+
injection/_core/common/invertible.py,sha256=a-fht4TxMnki-oFFaZrDz52X_LWx0NU60KQlw72pzs4,528
|
|
7
|
+
injection/_core/common/lazy.py,sha256=id5XWqk366ZcOpbd1svaLj3rqWVM9f1ZFQV5PVWnDTc,1321
|
|
8
|
+
injection/_core/common/threading.py,sha256=-JHNOKgTAQaCannZsL9xiivokvO61HEs_sPtcLrABk4,243
|
|
9
|
+
injection/_core/common/type.py,sha256=F95TtldxpYcEa7wcxoTZGr2XUGWlWb2TtFNRPeopKwM,1812
|
|
10
|
+
injection/_core/module.py,sha256=gKFs094UahR8wgEfOMskB5LMhTDQBXQH6skByHq7AjE,22919
|
|
11
|
+
injection/exceptions.py,sha256=RsWWiWwKSMU0vxXQqQSn6CKHLMrGu4SSzYUAy9OJRXk,626
|
|
12
|
+
injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
injection/integrations/blacksheep.py,sha256=W6gscAojoPhjvYJJ1Z7Zj5EjR0beJmfoLFDq6ijdJUg,711
|
|
14
|
+
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
injection/testing/__init__.py,sha256=RsdMF6HOK8n_vyy7siiKuHkIR13dclMQK3SUUP5FmsE,855
|
|
16
|
+
injection/testing/__init__.pyi,sha256=FggXsbHllXTaaiW1kYDZCkA1tpkNpBW8wkRUIt8Yg9Y,511
|
|
17
|
+
injection/utils.py,sha256=sPQXzhsvUUZ3dIRu_IyNhWYgNROY5SEYk7bXQYcId9s,1171
|
|
18
|
+
python_injection-0.9.7.dist-info/METADATA,sha256=6HS9TdMjFAOQCPMVQttPbJXL02Kn8ReMw-2Qd1iB1Lo,4624
|
|
19
|
+
python_injection-0.9.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
20
|
+
python_injection-0.9.7.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
injection/__init__.py,sha256=4kwoQN5V-fcasIbZ3G3_zCbmnvGCqTilJ92Lwu62wXc,798
|
|
2
|
-
injection/__init__.pyi,sha256=wdZ6l_9LgoUDM-QC8PNq2Y4RxKisnlE89Fhxov_ujvk,6399
|
|
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=a-fht4TxMnki-oFFaZrDz52X_LWx0NU60KQlw72pzs4,528
|
|
6
|
-
injection/common/lazy.py,sha256=SpQhlGBpMpeD9R5R-CdIInSVDv1XZWvnkERp1J6wsus,1315
|
|
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=u6nJ14Z7CRqPj2JIbGd1SYRkFfL-bs5zZQE-ouf_UkY,1746
|
|
10
|
-
injection/core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
|
|
11
|
-
injection/core/module.py,sha256=9Kv9wa37yknlGy3xwfovE0ZRJs350VIBbl3SIYjXr_w,22157
|
|
12
|
-
injection/exceptions.py,sha256=RsWWiWwKSMU0vxXQqQSn6CKHLMrGu4SSzYUAy9OJRXk,626
|
|
13
|
-
injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
injection/integrations/blacksheep.py,sha256=W6gscAojoPhjvYJJ1Z7Zj5EjR0beJmfoLFDq6ijdJUg,711
|
|
15
|
-
injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
injection/testing/__init__.py,sha256=haC6VtEfwupbpfuq-cIR_AFZOxTMrNwG_OT3c9z2pCE,814
|
|
17
|
-
injection/testing/__init__.pyi,sha256=1L-C_6mRaL_8o3EChkrf7qAkNjhoojcxNf3HVdt5WWo,484
|
|
18
|
-
injection/utils.py,sha256=0nOJwQNqjeAAPVKdHTFdYczxPQVekbFeXhjJCEQmom8,1121
|
|
19
|
-
python_injection-0.9.5.dist-info/METADATA,sha256=uJUl9D0_QomYu2kqOdvK8pTBv7zfHDNpUPAqmaqJRhs,4156
|
|
20
|
-
python_injection-0.9.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
21
|
-
python_injection-0.9.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|