python-injection 0.8.1.post0__tar.gz → 0.8.3__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.
Potentially problematic release.
This version of python-injection might be problematic. Click here for more details.
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/PKG-INFO +3 -3
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/documentation/basic-usage.md +2 -2
- python_injection-0.8.1.post0/injection/_pkg.py → python_injection-0.8.3/injection/__init__.py +2 -1
- python_injection-0.8.1.post0/injection/_pkg.pyi → python_injection-0.8.3/injection/__init__.pyi +28 -10
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/core/module.py +125 -63
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/pyproject.toml +1 -1
- python_injection-0.8.1.post0/injection/__init__.py +0 -1
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/__init__.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/event.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/invertible.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/lazy.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/queue.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/tools/__init__.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/tools/threading.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/common/tools/type.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/core/__init__.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/exceptions.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/integrations/__init__.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/integrations/blacksheep.py +0 -0
- {python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-injection
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: Fast and easy dependency injection framework.
|
|
5
5
|
Home-page: https://github.com/100nm/python-injection
|
|
6
6
|
License: MIT
|
|
@@ -136,7 +136,7 @@ class ConcreteServiceOverload(ConcreteService):
|
|
|
136
136
|
...
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
If a class is registered in a package and you want to override it, there is the `
|
|
139
|
+
If a class is registered in a package, and you want to override it, there is the `mode` parameter:
|
|
140
140
|
|
|
141
141
|
```python
|
|
142
142
|
@injectable
|
|
@@ -145,7 +145,7 @@ class InaccessibleService:
|
|
|
145
145
|
|
|
146
146
|
# ...
|
|
147
147
|
|
|
148
|
-
@injectable(on=InaccessibleService, override
|
|
148
|
+
@injectable(on=InaccessibleService, mode="override")
|
|
149
149
|
class ServiceOverload(InaccessibleService):
|
|
150
150
|
...
|
|
151
151
|
```
|
|
@@ -119,7 +119,7 @@ class ConcreteServiceOverload(ConcreteService):
|
|
|
119
119
|
...
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
If a class is registered in a package and you want to override it, there is the `
|
|
122
|
+
If a class is registered in a package, and you want to override it, there is the `mode` parameter:
|
|
123
123
|
|
|
124
124
|
```python
|
|
125
125
|
@injectable
|
|
@@ -128,7 +128,7 @@ class InaccessibleService:
|
|
|
128
128
|
|
|
129
129
|
# ...
|
|
130
130
|
|
|
131
|
-
@injectable(on=InaccessibleService, override
|
|
131
|
+
@injectable(on=InaccessibleService, mode="override")
|
|
132
132
|
class ServiceOverload(InaccessibleService):
|
|
133
133
|
...
|
|
134
134
|
```
|
python_injection-0.8.1.post0/injection/_pkg.pyi → python_injection-0.8.3/injection/__init__.pyi
RENAMED
|
@@ -7,13 +7,14 @@ from typing import (
|
|
|
7
7
|
Any,
|
|
8
8
|
ContextManager,
|
|
9
9
|
Final,
|
|
10
|
+
Literal,
|
|
10
11
|
Protocol,
|
|
11
12
|
TypeVar,
|
|
12
13
|
final,
|
|
13
14
|
runtime_checkable,
|
|
14
15
|
)
|
|
15
16
|
|
|
16
|
-
from
|
|
17
|
+
from .common.invertible import Invertible
|
|
17
18
|
|
|
18
19
|
_T = TypeVar("_T")
|
|
19
20
|
|
|
@@ -54,7 +55,7 @@ class Module:
|
|
|
54
55
|
cls: type[Injectable] = ...,
|
|
55
56
|
inject: bool = ...,
|
|
56
57
|
on: type | Iterable[type] | UnionType = ...,
|
|
57
|
-
|
|
58
|
+
mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
|
|
58
59
|
):
|
|
59
60
|
"""
|
|
60
61
|
Decorator applicable to a class or function. It is used to indicate how the
|
|
@@ -69,7 +70,7 @@ class Module:
|
|
|
69
70
|
*,
|
|
70
71
|
inject: bool = ...,
|
|
71
72
|
on: type | Iterable[type] | UnionType = ...,
|
|
72
|
-
|
|
73
|
+
mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
|
|
73
74
|
):
|
|
74
75
|
"""
|
|
75
76
|
Decorator applicable to a class or function. It is used to indicate how the
|
|
@@ -89,7 +90,7 @@ class Module:
|
|
|
89
90
|
instance: _T,
|
|
90
91
|
on: type | Iterable[type] | UnionType = ...,
|
|
91
92
|
*,
|
|
92
|
-
|
|
93
|
+
mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
|
|
93
94
|
) -> _T:
|
|
94
95
|
"""
|
|
95
96
|
Function for registering a specific instance to be injected. This is useful for
|
|
@@ -97,7 +98,7 @@ class Module:
|
|
|
97
98
|
that no dependencies are resolved, so the module doesn't need to be locked.
|
|
98
99
|
"""
|
|
99
100
|
|
|
100
|
-
def get_instance(self, cls: type[_T], none: bool = ...) -> _T | None:
|
|
101
|
+
def get_instance(self, cls: type[_T], *, none: bool = ...) -> _T | None:
|
|
101
102
|
"""
|
|
102
103
|
Function used to retrieve an instance associated with the type passed in
|
|
103
104
|
parameter or return `None` but if `none` parameter is `False` an exception
|
|
@@ -107,6 +108,7 @@ class Module:
|
|
|
107
108
|
def get_lazy_instance(
|
|
108
109
|
self,
|
|
109
110
|
cls: type[_T],
|
|
111
|
+
*,
|
|
110
112
|
cache: bool = ...,
|
|
111
113
|
) -> Invertible[_T | None]:
|
|
112
114
|
"""
|
|
@@ -118,7 +120,12 @@ class Module:
|
|
|
118
120
|
Example: instance = ~lazy_instance
|
|
119
121
|
"""
|
|
120
122
|
|
|
121
|
-
def use(
|
|
123
|
+
def use(
|
|
124
|
+
self,
|
|
125
|
+
module: Module,
|
|
126
|
+
*,
|
|
127
|
+
priority: ModulePriority | Literal["low", "high"] = ...,
|
|
128
|
+
):
|
|
122
129
|
"""
|
|
123
130
|
Function for using another module. Using another module replaces the module's
|
|
124
131
|
dependencies with those of the module used. If the dependency is not found, it
|
|
@@ -133,13 +140,18 @@ class Module:
|
|
|
133
140
|
def use_temporarily(
|
|
134
141
|
self,
|
|
135
142
|
module: Module,
|
|
136
|
-
|
|
143
|
+
*,
|
|
144
|
+
priority: ModulePriority | Literal["low", "high"] = ...,
|
|
137
145
|
) -> ContextManager | ContextDecorator:
|
|
138
146
|
"""
|
|
139
147
|
Context manager or decorator for temporary use of a module.
|
|
140
148
|
"""
|
|
141
149
|
|
|
142
|
-
def change_priority(
|
|
150
|
+
def change_priority(
|
|
151
|
+
self,
|
|
152
|
+
module: Module,
|
|
153
|
+
priority: ModulePriority | Literal["low", "high"],
|
|
154
|
+
):
|
|
143
155
|
"""
|
|
144
156
|
Function for changing the priority of a module in use.
|
|
145
157
|
There are two priority values:
|
|
@@ -154,9 +166,9 @@ class Module:
|
|
|
154
166
|
"""
|
|
155
167
|
|
|
156
168
|
@final
|
|
157
|
-
class ModulePriority(Enum):
|
|
158
|
-
HIGH = ...
|
|
169
|
+
class ModulePriority(str, Enum):
|
|
159
170
|
LOW = ...
|
|
171
|
+
HIGH = ...
|
|
160
172
|
|
|
161
173
|
@runtime_checkable
|
|
162
174
|
class Injectable(Protocol[_T]):
|
|
@@ -166,3 +178,9 @@ class Injectable(Protocol[_T]):
|
|
|
166
178
|
def unlock(self): ...
|
|
167
179
|
@abstractmethod
|
|
168
180
|
def get_instance(self) -> _T: ...
|
|
181
|
+
|
|
182
|
+
@final
|
|
183
|
+
class InjectableMode(str, Enum):
|
|
184
|
+
FALLBACK = ...
|
|
185
|
+
NORMAL = ...
|
|
186
|
+
OVERRIDE = ...
|
|
@@ -11,11 +11,10 @@ from collections.abc import (
|
|
|
11
11
|
Iterator,
|
|
12
12
|
Mapping,
|
|
13
13
|
MutableMapping,
|
|
14
|
-
Set,
|
|
15
14
|
)
|
|
16
15
|
from contextlib import ContextDecorator, contextmanager, suppress
|
|
17
16
|
from dataclasses import dataclass, field
|
|
18
|
-
from enum import Enum
|
|
17
|
+
from enum import Enum
|
|
19
18
|
from functools import partialmethod, singledispatchmethod, update_wrapper
|
|
20
19
|
from inspect import Signature, isclass
|
|
21
20
|
from types import MethodType, UnionType
|
|
@@ -23,6 +22,7 @@ from typing import (
|
|
|
23
22
|
Any,
|
|
24
23
|
ClassVar,
|
|
25
24
|
ContextManager,
|
|
25
|
+
Literal,
|
|
26
26
|
NamedTuple,
|
|
27
27
|
NoReturn,
|
|
28
28
|
Protocol,
|
|
@@ -45,12 +45,12 @@ from injection.exceptions import (
|
|
|
45
45
|
NoInjectable,
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
__all__ = ("Injectable", "Module", "ModulePriority")
|
|
48
|
+
__all__ = ("Injectable", "InjectableMode", "Module", "ModulePriority")
|
|
49
49
|
|
|
50
50
|
_logger = logging.getLogger(__name__)
|
|
51
51
|
|
|
52
52
|
_T = TypeVar("_T")
|
|
53
|
-
|
|
53
|
+
_Types = Iterable[type] | UnionType
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
"""
|
|
@@ -66,7 +66,7 @@ class ContainerEvent(Event, ABC):
|
|
|
66
66
|
@dataclass(frozen=True, slots=True)
|
|
67
67
|
class ContainerDependenciesUpdated(ContainerEvent):
|
|
68
68
|
classes: Collection[type]
|
|
69
|
-
|
|
69
|
+
mode: InjectableMode
|
|
70
70
|
|
|
71
71
|
def __str__(self) -> str:
|
|
72
72
|
length = len(self.classes)
|
|
@@ -104,6 +104,7 @@ class ModuleEventProxy(ModuleEvent):
|
|
|
104
104
|
@dataclass(frozen=True, slots=True)
|
|
105
105
|
class ModuleAdded(ModuleEvent):
|
|
106
106
|
module_added: Module
|
|
107
|
+
priority: ModulePriority
|
|
107
108
|
|
|
108
109
|
def __str__(self) -> str:
|
|
109
110
|
return f"`{self.on_module}` now uses `{self.module_added}`."
|
|
@@ -124,7 +125,7 @@ class ModulePriorityUpdated(ModuleEvent):
|
|
|
124
125
|
|
|
125
126
|
def __str__(self) -> str:
|
|
126
127
|
return (
|
|
127
|
-
f"In `{self.on_module}`, the priority `{self.priority
|
|
128
|
+
f"In `{self.on_module}`, the priority `{self.priority}` "
|
|
128
129
|
f"has been applied to `{self.module_updated}`."
|
|
129
130
|
)
|
|
130
131
|
|
|
@@ -153,13 +154,6 @@ class Injectable(Protocol[_T]):
|
|
|
153
154
|
raise NotImplementedError
|
|
154
155
|
|
|
155
156
|
|
|
156
|
-
class FallbackInjectable(Injectable[_T], ABC):
|
|
157
|
-
__slots__ = ()
|
|
158
|
-
|
|
159
|
-
def __bool__(self) -> bool:
|
|
160
|
-
return False
|
|
161
|
-
|
|
162
|
-
|
|
163
157
|
@dataclass(repr=False, frozen=True, slots=True)
|
|
164
158
|
class BaseInjectable(Injectable[_T], ABC):
|
|
165
159
|
factory: Callable[[], _T]
|
|
@@ -200,7 +194,7 @@ class SingletonInjectable(BaseInjectable[_T]):
|
|
|
200
194
|
|
|
201
195
|
|
|
202
196
|
@dataclass(repr=False, frozen=True, slots=True)
|
|
203
|
-
class ShouldBeInjectable(
|
|
197
|
+
class ShouldBeInjectable(Injectable[_T]):
|
|
204
198
|
cls: type[_T]
|
|
205
199
|
|
|
206
200
|
def get_instance(self) -> NoReturn:
|
|
@@ -239,49 +233,68 @@ Container
|
|
|
239
233
|
"""
|
|
240
234
|
|
|
241
235
|
|
|
236
|
+
class InjectableMode(str, Enum):
|
|
237
|
+
FALLBACK = "fallback"
|
|
238
|
+
NORMAL = "normal"
|
|
239
|
+
OVERRIDE = "override"
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def rank(self) -> int:
|
|
243
|
+
return tuple(type(self)).index(self)
|
|
244
|
+
|
|
245
|
+
@classmethod
|
|
246
|
+
def get_default(cls):
|
|
247
|
+
return cls.NORMAL
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
_Mode = InjectableMode | Literal["fallback", "normal", "override"]
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class Record(NamedTuple):
|
|
254
|
+
injectable: Injectable
|
|
255
|
+
mode: InjectableMode
|
|
256
|
+
|
|
257
|
+
|
|
242
258
|
@dataclass(repr=False, frozen=True, slots=True)
|
|
243
259
|
class Container(Broker):
|
|
244
|
-
|
|
260
|
+
__records: dict[type, Record] = field(default_factory=dict, init=False)
|
|
245
261
|
__channel: EventChannel = field(default_factory=EventChannel, init=False)
|
|
246
262
|
|
|
247
263
|
def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
|
|
248
|
-
for
|
|
249
|
-
|
|
250
|
-
|
|
264
|
+
for cls in get_origins(cls):
|
|
265
|
+
try:
|
|
266
|
+
injectable, _ = self.__records[cls]
|
|
267
|
+
except KeyError:
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
return injectable
|
|
251
271
|
|
|
252
272
|
raise NoInjectable(cls)
|
|
253
273
|
|
|
254
274
|
def __contains__(self, cls: type | UnionType, /) -> bool:
|
|
255
|
-
return any(
|
|
275
|
+
return any(cls in self.__records for cls in get_origins(cls))
|
|
256
276
|
|
|
257
277
|
@property
|
|
258
278
|
def is_locked(self) -> bool:
|
|
259
279
|
return any(injectable.is_locked for injectable in self.__injectables)
|
|
260
280
|
|
|
261
|
-
@property
|
|
262
|
-
def __classes(self) -> frozenset[type]:
|
|
263
|
-
return frozenset(self.__data)
|
|
264
|
-
|
|
265
281
|
@property
|
|
266
282
|
def __injectables(self) -> frozenset[Injectable]:
|
|
267
|
-
return frozenset(self.
|
|
283
|
+
return frozenset(injectable for injectable, _ in self.__records.values())
|
|
268
284
|
|
|
269
285
|
@synchronized()
|
|
270
|
-
def update(self, classes: Iterable[type], injectable: Injectable,
|
|
271
|
-
|
|
286
|
+
def update(self, classes: Iterable[type], injectable: Injectable, mode: _Mode):
|
|
287
|
+
mode = InjectableMode(mode)
|
|
288
|
+
records = {
|
|
289
|
+
cls: Record(injectable, mode)
|
|
290
|
+
for cls in self.__filter_classes(classes, mode)
|
|
291
|
+
}
|
|
272
292
|
|
|
273
|
-
if
|
|
274
|
-
|
|
275
|
-
override = True
|
|
276
|
-
|
|
277
|
-
if classes:
|
|
278
|
-
event = ContainerDependenciesUpdated(self, classes, override)
|
|
293
|
+
if records:
|
|
294
|
+
event = ContainerDependenciesUpdated(self, records.keys(), mode)
|
|
279
295
|
|
|
280
296
|
with self.notify(event):
|
|
281
|
-
|
|
282
|
-
self.__check_if_exists(classes)
|
|
283
|
-
|
|
284
|
-
self.__data.update((cls, injectable) for cls in classes)
|
|
297
|
+
self.__records.update(records)
|
|
285
298
|
|
|
286
299
|
return self
|
|
287
300
|
|
|
@@ -299,14 +312,30 @@ class Container(Broker):
|
|
|
299
312
|
def notify(self, event: Event) -> ContextManager | ContextDecorator:
|
|
300
313
|
return self.__channel.dispatch(event)
|
|
301
314
|
|
|
302
|
-
def
|
|
303
|
-
|
|
315
|
+
def __filter_classes(
|
|
316
|
+
self,
|
|
317
|
+
classes: Iterable[type],
|
|
318
|
+
mode: InjectableMode,
|
|
319
|
+
) -> Iterator[type]:
|
|
320
|
+
rank = mode.rank
|
|
321
|
+
|
|
322
|
+
for cls in frozenset(get_origins(*classes)):
|
|
323
|
+
try:
|
|
324
|
+
_, current_mode = self.__records[cls]
|
|
325
|
+
|
|
326
|
+
except KeyError:
|
|
327
|
+
pass
|
|
328
|
+
|
|
329
|
+
else:
|
|
330
|
+
if mode == current_mode:
|
|
331
|
+
raise RuntimeError(
|
|
332
|
+
f"An injectable already exists for the class `{format_type(cls)}`."
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
elif rank < current_mode.rank:
|
|
336
|
+
continue
|
|
304
337
|
|
|
305
|
-
|
|
306
|
-
if self.__data[cls]:
|
|
307
|
-
raise RuntimeError(
|
|
308
|
-
f"An injectable already exists for the class `{format_type(cls)}`."
|
|
309
|
-
)
|
|
338
|
+
yield cls
|
|
310
339
|
|
|
311
340
|
|
|
312
341
|
"""
|
|
@@ -314,15 +343,18 @@ Module
|
|
|
314
343
|
"""
|
|
315
344
|
|
|
316
345
|
|
|
317
|
-
class ModulePriority(Enum):
|
|
318
|
-
|
|
319
|
-
|
|
346
|
+
class ModulePriority(str, Enum):
|
|
347
|
+
LOW = "low"
|
|
348
|
+
HIGH = "high"
|
|
320
349
|
|
|
321
350
|
@classmethod
|
|
322
351
|
def get_default(cls):
|
|
323
352
|
return cls.LOW
|
|
324
353
|
|
|
325
354
|
|
|
355
|
+
_Priority = ModulePriority | Literal["low", "high"]
|
|
356
|
+
|
|
357
|
+
|
|
326
358
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
327
359
|
class Module(EventListener, Broker):
|
|
328
360
|
name: str = field(default=None)
|
|
@@ -368,14 +400,14 @@ class Module(EventListener, Broker):
|
|
|
368
400
|
*,
|
|
369
401
|
cls: type[Injectable] = NewInjectable,
|
|
370
402
|
inject: bool = True,
|
|
371
|
-
on: type |
|
|
372
|
-
|
|
403
|
+
on: type | _Types = None,
|
|
404
|
+
mode: _Mode = InjectableMode.get_default(),
|
|
373
405
|
):
|
|
374
406
|
def decorator(wp):
|
|
375
407
|
factory = self.inject(wp, return_factory=True) if inject else wp
|
|
376
408
|
injectable = cls(factory)
|
|
377
409
|
classes = find_types(wp, on)
|
|
378
|
-
self.update(classes, injectable,
|
|
410
|
+
self.update(classes, injectable, mode)
|
|
379
411
|
return wp
|
|
380
412
|
|
|
381
413
|
return decorator(wrapped) if wrapped else decorator
|
|
@@ -384,7 +416,11 @@ class Module(EventListener, Broker):
|
|
|
384
416
|
|
|
385
417
|
def should_be_injectable(self, wrapped: type = None, /):
|
|
386
418
|
def decorator(wp):
|
|
387
|
-
self
|
|
419
|
+
self.update(
|
|
420
|
+
(wp,),
|
|
421
|
+
ShouldBeInjectable(wp),
|
|
422
|
+
mode=InjectableMode.FALLBACK,
|
|
423
|
+
)
|
|
388
424
|
return wp
|
|
389
425
|
|
|
390
426
|
return decorator(wrapped) if wrapped else decorator
|
|
@@ -392,16 +428,16 @@ class Module(EventListener, Broker):
|
|
|
392
428
|
def set_constant(
|
|
393
429
|
self,
|
|
394
430
|
instance: _T,
|
|
395
|
-
on: type |
|
|
431
|
+
on: type | _Types = None,
|
|
396
432
|
*,
|
|
397
|
-
|
|
433
|
+
mode: _Mode = InjectableMode.get_default(),
|
|
398
434
|
) -> _T:
|
|
399
435
|
cls = type(instance)
|
|
400
436
|
self.injectable(
|
|
401
437
|
lambda: instance,
|
|
402
438
|
inject=False,
|
|
403
439
|
on=(cls, on),
|
|
404
|
-
|
|
440
|
+
mode=mode,
|
|
405
441
|
)
|
|
406
442
|
return instance
|
|
407
443
|
|
|
@@ -428,7 +464,7 @@ class Module(EventListener, Broker):
|
|
|
428
464
|
|
|
429
465
|
return decorator(wrapped) if wrapped else decorator
|
|
430
466
|
|
|
431
|
-
def get_instance(self, cls: type[_T], none: bool = True) -> _T | None:
|
|
467
|
+
def get_instance(self, cls: type[_T], *, none: bool = True) -> _T | None:
|
|
432
468
|
try:
|
|
433
469
|
injectable = self[cls]
|
|
434
470
|
except KeyError as exc:
|
|
@@ -443,6 +479,7 @@ class Module(EventListener, Broker):
|
|
|
443
479
|
def get_lazy_instance(
|
|
444
480
|
self,
|
|
445
481
|
cls: type[_T],
|
|
482
|
+
*,
|
|
446
483
|
cache: bool = False,
|
|
447
484
|
) -> Invertible[_T | None]:
|
|
448
485
|
if cache:
|
|
@@ -456,15 +493,16 @@ class Module(EventListener, Broker):
|
|
|
456
493
|
self,
|
|
457
494
|
classes: Iterable[type],
|
|
458
495
|
injectable: Injectable,
|
|
459
|
-
|
|
496
|
+
mode: _Mode = InjectableMode.get_default(),
|
|
460
497
|
):
|
|
461
|
-
self.__container.update(classes, injectable,
|
|
498
|
+
self.__container.update(classes, injectable, mode)
|
|
462
499
|
return self
|
|
463
500
|
|
|
464
501
|
def use(
|
|
465
502
|
self,
|
|
466
503
|
module: Module,
|
|
467
|
-
|
|
504
|
+
*,
|
|
505
|
+
priority: _Priority = ModulePriority.get_default(),
|
|
468
506
|
):
|
|
469
507
|
if module is self:
|
|
470
508
|
raise ModuleError("Module can't be used by itself.")
|
|
@@ -472,7 +510,8 @@ class Module(EventListener, Broker):
|
|
|
472
510
|
if module in self.__modules:
|
|
473
511
|
raise ModuleError(f"`{self}` already uses `{module}`.")
|
|
474
512
|
|
|
475
|
-
|
|
513
|
+
priority = ModulePriority(priority)
|
|
514
|
+
event = ModuleAdded(self, module, priority)
|
|
476
515
|
|
|
477
516
|
with self.notify(event):
|
|
478
517
|
self.__modules[module] = None
|
|
@@ -495,13 +534,15 @@ class Module(EventListener, Broker):
|
|
|
495
534
|
def use_temporarily(
|
|
496
535
|
self,
|
|
497
536
|
module: Module,
|
|
498
|
-
|
|
537
|
+
*,
|
|
538
|
+
priority: _Priority = ModulePriority.get_default(),
|
|
499
539
|
) -> ContextManager | ContextDecorator:
|
|
500
|
-
self.use(module, priority)
|
|
540
|
+
self.use(module, priority=priority)
|
|
501
541
|
yield
|
|
502
542
|
self.stop_using(module)
|
|
503
543
|
|
|
504
|
-
def change_priority(self, module: Module, priority:
|
|
544
|
+
def change_priority(self, module: Module, priority: _Priority):
|
|
545
|
+
priority = ModulePriority(priority)
|
|
505
546
|
event = ModulePriorityUpdated(self, module, priority)
|
|
506
547
|
|
|
507
548
|
with self.notify(event):
|
|
@@ -541,7 +582,7 @@ class Module(EventListener, Broker):
|
|
|
541
582
|
raise ModuleLockError(f"`{self}` is locked.")
|
|
542
583
|
|
|
543
584
|
def __move_module(self, module: Module, priority: ModulePriority):
|
|
544
|
-
last = priority
|
|
585
|
+
last = priority != ModulePriority.HIGH
|
|
545
586
|
|
|
546
587
|
try:
|
|
547
588
|
self.__modules.move_to_end(module, last=last)
|
|
@@ -637,7 +678,8 @@ class InjectedFunction(EventListener):
|
|
|
637
678
|
)
|
|
638
679
|
|
|
639
680
|
def __init__(self, wrapped: Callable[..., Any], /):
|
|
640
|
-
|
|
681
|
+
self.__update_vars_from(wrapped)
|
|
682
|
+
update_wrapper(self, wrapped, updated=())
|
|
641
683
|
self.__dependencies = Dependencies.empty()
|
|
642
684
|
self.__owner = None
|
|
643
685
|
self.__setup_queue = LimitedQueue[Callable[[], Any]]()
|
|
@@ -727,3 +769,23 @@ class InjectedFunction(EventListener):
|
|
|
727
769
|
def __set_signature(self):
|
|
728
770
|
self.__signature__ = inspect.signature(self.wrapped, eval_str=True)
|
|
729
771
|
return self
|
|
772
|
+
|
|
773
|
+
def __update_vars_from(self, obj: Any):
|
|
774
|
+
try:
|
|
775
|
+
variables = vars(obj)
|
|
776
|
+
except TypeError:
|
|
777
|
+
pass
|
|
778
|
+
else:
|
|
779
|
+
self.__update_vars(variables)
|
|
780
|
+
|
|
781
|
+
def __update_vars(self, variables: Mapping[str, Any]):
|
|
782
|
+
def is_dunder(var: str) -> bool:
|
|
783
|
+
return var.startswith("__") and var.endswith("__")
|
|
784
|
+
|
|
785
|
+
restricted_vars = frozenset(var for var in dir(self) if not is_dunder(var))
|
|
786
|
+
variables = (
|
|
787
|
+
(var, value)
|
|
788
|
+
for var, value in variables.items()
|
|
789
|
+
if var not in restricted_vars
|
|
790
|
+
)
|
|
791
|
+
vars(self).update(variables)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from ._pkg import *
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_injection-0.8.1.post0 → python_injection-0.8.3}/injection/integrations/blacksheep.py
RENAMED
|
File without changes
|
|
File without changes
|