python-injection 0.19.3__tar.gz → 0.19.5__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.
Files changed (32) hide show
  1. {python_injection-0.19.3 → python_injection-0.19.5}/PKG-INFO +1 -1
  2. {python_injection-0.19.3 → python_injection-0.19.5}/injection/__init__.pyi +177 -13
  3. python_injection-0.19.5/injection/_core/common/lazy.py +50 -0
  4. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/type.py +2 -1
  5. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/module.py +3 -3
  6. {python_injection-0.19.3 → python_injection-0.19.5}/injection/entrypoint.py +14 -3
  7. {python_injection-0.19.3 → python_injection-0.19.5}/pyproject.toml +1 -1
  8. python_injection-0.19.3/injection/_core/common/lazy.py +0 -41
  9. {python_injection-0.19.3 → python_injection-0.19.5}/.gitignore +0 -0
  10. {python_injection-0.19.3 → python_injection-0.19.5}/LICENSE +0 -0
  11. {python_injection-0.19.3 → python_injection-0.19.5}/README.md +0 -0
  12. {python_injection-0.19.3 → python_injection-0.19.5}/injection/__init__.py +0 -0
  13. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/__init__.py +0 -0
  14. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/asfunction.py +0 -0
  15. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/__init__.py +0 -0
  16. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/asynchronous.py +0 -0
  17. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/event.py +0 -0
  18. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/invertible.py +0 -0
  19. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/key.py +0 -0
  20. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/common/threading.py +0 -0
  21. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/descriptors.py +0 -0
  22. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/injectables.py +0 -0
  23. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/scope.py +0 -0
  24. {python_injection-0.19.3 → python_injection-0.19.5}/injection/_core/slots.py +0 -0
  25. {python_injection-0.19.3 → python_injection-0.19.5}/injection/exceptions.py +0 -0
  26. {python_injection-0.19.3 → python_injection-0.19.5}/injection/ext/__init__.py +0 -0
  27. {python_injection-0.19.3 → python_injection-0.19.5}/injection/ext/fastapi.py +0 -0
  28. {python_injection-0.19.3 → python_injection-0.19.5}/injection/ext/fastapi.pyi +0 -0
  29. {python_injection-0.19.3 → python_injection-0.19.5}/injection/loaders.py +0 -0
  30. {python_injection-0.19.3 → python_injection-0.19.5}/injection/py.typed +0 -0
  31. {python_injection-0.19.3 → python_injection-0.19.5}/injection/testing/__init__.py +0 -0
  32. {python_injection-0.19.3 → python_injection-0.19.5}/injection/testing/__init__.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-injection
3
- Version: 0.19.3
3
+ Version: 0.19.5
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Project-URL: Repository, https://github.com/100nm/python-injection
6
6
  Author: remimd
@@ -11,9 +11,10 @@ from ._core.common.type import InputType as _InputType
11
11
  from ._core.common.type import TypeInfo as _TypeInfo
12
12
  from ._core.module import InjectableFactory as _InjectableFactory
13
13
  from ._core.module import ModeStr, PriorityStr
14
- from ._core.module import Recipe as _Recipe
15
14
  from ._core.scope import ScopeKindStr
16
15
 
16
+ type _Decorator[T] = Callable[[T], T]
17
+
17
18
  __MODULE: Final[Module] = ...
18
19
 
19
20
  afind_instance = __MODULE.afind_instance
@@ -120,13 +121,14 @@ class Module:
120
121
  def __contains__(self, cls: _InputType[Any], /) -> bool: ...
121
122
  @property
122
123
  def is_locked(self) -> bool: ...
124
+ @overload
123
125
  def inject[**P, T](
124
126
  self,
125
- wrapped: Callable[P, T] = ...,
127
+ wrapped: Callable[P, T],
126
128
  /,
127
129
  *,
128
130
  threadsafe: bool | None = ...,
129
- ) -> Any:
131
+ ) -> Callable[P, T]:
130
132
  """
131
133
  Decorator applicable to a class or function. Inject function dependencies using
132
134
  parameter type annotations. If applied to a class, the dependencies resolved
@@ -134,74 +136,236 @@ class Module:
134
136
 
135
137
  With `threadsafe=True`, the injection logic is wrapped in a `threading.RLock`.
136
138
  """
137
-
139
+ @overload
140
+ def inject[T](
141
+ self,
142
+ wrapped: type[T],
143
+ /,
144
+ *,
145
+ threadsafe: bool | None = ...,
146
+ ) -> type[T]: ...
147
+ @overload
148
+ def inject(
149
+ self,
150
+ wrapped: None = ...,
151
+ /,
152
+ *,
153
+ threadsafe: bool | None = ...,
154
+ ) -> _Decorator[Callable[..., Any] | type]: ...
155
+ @overload
138
156
  def injectable[**P, T](
139
157
  self,
140
- wrapped: _Recipe[P, T] = ...,
158
+ wrapped: Callable[P, T],
141
159
  /,
142
160
  *,
143
161
  cls: _InjectableFactory[T] = ...,
144
162
  inject: bool = ...,
145
163
  on: _TypeInfo[T] = ...,
146
164
  mode: Mode | ModeStr = ...,
147
- ) -> Any:
165
+ ) -> Callable[P, T]:
148
166
  """
149
167
  Decorator applicable to a class or function. It is used to indicate how the
150
168
  injectable will be constructed. At injection time, a new instance will be
151
169
  injected each time.
152
170
  """
153
171
 
172
+ @overload
173
+ def injectable[**P, T]( # type: ignore[overload-overlap]
174
+ self,
175
+ wrapped: Callable[P, Awaitable[T]],
176
+ /,
177
+ *,
178
+ cls: _InjectableFactory[T] = ...,
179
+ inject: bool = ...,
180
+ on: _TypeInfo[T] = ...,
181
+ mode: Mode | ModeStr = ...,
182
+ ) -> Callable[P, Awaitable[T]]: ...
183
+ @overload
184
+ def injectable[T](
185
+ self,
186
+ wrapped: type[T],
187
+ /,
188
+ *,
189
+ cls: _InjectableFactory[T] = ...,
190
+ inject: bool = ...,
191
+ on: _TypeInfo[T] = ...,
192
+ mode: Mode | ModeStr = ...,
193
+ ) -> type[T]: ...
194
+ @overload
195
+ def injectable[T](
196
+ self,
197
+ wrapped: None = ...,
198
+ /,
199
+ *,
200
+ cls: _InjectableFactory[T] = ...,
201
+ inject: bool = ...,
202
+ on: _TypeInfo[T],
203
+ mode: Mode | ModeStr = ...,
204
+ ) -> _Decorator[Callable[..., T] | Callable[..., Awaitable[T]] | type[T]]: ...
205
+ @overload
206
+ def injectable(
207
+ self,
208
+ wrapped: None = ...,
209
+ /,
210
+ *,
211
+ cls: _InjectableFactory[Any] = ...,
212
+ inject: bool = ...,
213
+ on: tuple[()] = ...,
214
+ mode: Mode | ModeStr = ...,
215
+ ) -> _Decorator[Callable[..., Any] | type]: ...
216
+ @overload
154
217
  def singleton[**P, T](
155
218
  self,
156
- wrapped: _Recipe[P, T] = ...,
219
+ wrapped: Callable[P, T],
157
220
  /,
158
221
  *,
159
222
  inject: bool = ...,
160
223
  on: _TypeInfo[T] = ...,
161
224
  mode: Mode | ModeStr = ...,
162
- ) -> Any:
225
+ ) -> Callable[P, T]:
163
226
  """
164
227
  Decorator applicable to a class or function. It is used to indicate how the
165
228
  singleton will be constructed. At injection time, the injected instance will
166
229
  always be the same.
167
230
  """
168
231
 
232
+ @overload
233
+ def singleton[**P, T]( # type: ignore[overload-overlap]
234
+ self,
235
+ wrapped: Callable[P, Awaitable[T]],
236
+ /,
237
+ *,
238
+ inject: bool = ...,
239
+ on: _TypeInfo[T] = ...,
240
+ mode: Mode | ModeStr = ...,
241
+ ) -> Callable[P, Awaitable[T]]: ...
242
+ @overload
243
+ def singleton[T](
244
+ self,
245
+ wrapped: type[T],
246
+ /,
247
+ *,
248
+ inject: bool = ...,
249
+ on: _TypeInfo[T] = ...,
250
+ mode: Mode | ModeStr = ...,
251
+ ) -> type[T]: ...
252
+ @overload
253
+ def singleton[T](
254
+ self,
255
+ wrapped: None = ...,
256
+ /,
257
+ *,
258
+ inject: bool = ...,
259
+ on: _TypeInfo[T],
260
+ mode: Mode | ModeStr = ...,
261
+ ) -> _Decorator[Callable[..., T] | Callable[..., Awaitable[T]] | type[T]]: ...
262
+ @overload
263
+ def singleton(
264
+ self,
265
+ wrapped: None = ...,
266
+ /,
267
+ *,
268
+ inject: bool = ...,
269
+ on: tuple[()] = ...,
270
+ mode: Mode | ModeStr = ...,
271
+ ) -> _Decorator[Callable[..., Any] | type]: ...
272
+ @overload
169
273
  def scoped[T](
170
274
  self,
171
275
  scope_name: str,
172
276
  /,
173
277
  *,
174
278
  inject: bool = ...,
175
- on: _TypeInfo[T] = (),
279
+ on: _TypeInfo[T],
176
280
  mode: Mode | ModeStr = ...,
177
- ) -> Any:
281
+ ) -> _Decorator[
282
+ Callable[..., T]
283
+ | Callable[..., Awaitable[T]]
284
+ | Callable[..., AsyncIterator[T]]
285
+ | Callable[..., Iterator[T]]
286
+ | type[T]
287
+ ]:
178
288
  """
179
289
  Decorator applicable to a class or function or generator function. It is used
180
290
  to indicate how the scoped instance will be constructed. At injection time, the
181
291
  injected instance is retrieved from the scope.
182
292
  """
183
293
 
184
- def should_be_injectable[T](self, wrapped: type[T] = ..., /) -> Any:
294
+ @overload
295
+ def scoped(
296
+ self,
297
+ scope_name: str,
298
+ /,
299
+ *,
300
+ inject: bool = ...,
301
+ on: tuple[()] = ...,
302
+ mode: Mode | ModeStr = ...,
303
+ ) -> _Decorator[Callable[..., Any] | type]: ...
304
+ @overload
305
+ def should_be_injectable[T](self, wrapped: type[T], /) -> type[T]:
185
306
  """
186
307
  Decorator applicable to a class. It is used to specify whether an injectable
187
308
  should be registered. Raise an exception at injection time if the class isn't
188
309
  registered.
189
310
  """
190
311
 
312
+ @overload
313
+ def should_be_injectable(
314
+ self,
315
+ wrapped: None = ...,
316
+ /,
317
+ ) -> _Decorator[type]: ...
318
+ @overload
191
319
  def constant[**P, T](
192
320
  self,
193
- wrapped: _Recipe[P, T] = ...,
321
+ wrapped: Callable[P, T],
194
322
  /,
195
323
  *,
196
324
  on: _TypeInfo[T] = ...,
197
325
  mode: Mode | ModeStr = ...,
198
- ) -> Any:
326
+ ) -> Callable[P, T]:
199
327
  """
200
328
  Decorator applicable to a class or function. It is used to indicate how the
201
329
  constant is constructed. At injection time, the injected instance will always
202
330
  be the same. Unlike `@singleton`, dependencies will not be resolved.
203
331
  """
204
332
 
333
+ @overload
334
+ def constant[**P, T]( # type: ignore[overload-overlap]
335
+ self,
336
+ wrapped: Callable[P, Awaitable[T]],
337
+ /,
338
+ *,
339
+ on: _TypeInfo[T] = ...,
340
+ mode: Mode | ModeStr = ...,
341
+ ) -> Callable[P, Awaitable[T]]: ...
342
+ @overload
343
+ def constant[T](
344
+ self,
345
+ wrapped: type[T],
346
+ /,
347
+ *,
348
+ on: _TypeInfo[T] = ...,
349
+ mode: Mode | ModeStr = ...,
350
+ ) -> type[T]: ...
351
+ @overload
352
+ def constant[T](
353
+ self,
354
+ wrapped: None = ...,
355
+ /,
356
+ *,
357
+ on: _TypeInfo[T],
358
+ mode: Mode | ModeStr = ...,
359
+ ) -> _Decorator[Callable[..., T] | Callable[..., Awaitable[T]] | type[T]]: ...
360
+ @overload
361
+ def constant(
362
+ self,
363
+ wrapped: None = ...,
364
+ /,
365
+ *,
366
+ on: tuple[()] = ...,
367
+ mode: Mode | ModeStr = ...,
368
+ ) -> _Decorator[Callable[..., Any] | type]: ...
205
369
  def set_constant[T](
206
370
  self,
207
371
  instance: T,
@@ -0,0 +1,50 @@
1
+ from collections.abc import AsyncIterator, Awaitable, Callable, Iterator
2
+ from functools import partial
3
+
4
+ from injection._core.common.invertible import Invertible
5
+
6
+
7
+ def lazy[T](factory: Callable[..., T]) -> Callable[[], T]:
8
+ def cache() -> Iterator[T]:
9
+ value = factory()
10
+ while True:
11
+ yield value
12
+
13
+ return partial(next, cache())
14
+
15
+
16
+ def alazy[T](factory: Callable[..., Awaitable[T]]) -> Callable[[], Awaitable[T]]:
17
+ async def cache() -> AsyncIterator[T]:
18
+ value = await factory()
19
+ while True:
20
+ yield value
21
+
22
+ return partial(_anext, cache())
23
+
24
+
25
+ class Lazy[T](Invertible[T]):
26
+ __slots__ = ("__get", "__is_set")
27
+
28
+ __get: Callable[[], T]
29
+ __is_set: bool
30
+
31
+ def __init__(self, factory: Callable[..., T]) -> None:
32
+ @lazy
33
+ def get() -> T:
34
+ value = factory()
35
+ self.__is_set = True
36
+ return value
37
+
38
+ self.__get = get
39
+ self.__is_set = False
40
+
41
+ def __invert__(self) -> T:
42
+ return self.__get()
43
+
44
+ @property
45
+ def is_set(self) -> bool:
46
+ return self.__is_set
47
+
48
+
49
+ async def _anext[T](async_iterator: AsyncIterator[T]) -> T:
50
+ return await anext(async_iterator)
@@ -7,6 +7,7 @@ from collections.abc import (
7
7
  Generator,
8
8
  Iterable,
9
9
  Iterator,
10
+ Sequence,
10
11
  )
11
12
  from inspect import isfunction
12
13
  from types import GenericAlias, UnionType
@@ -26,7 +27,7 @@ type TypeInfo[T] = (
26
27
  InputType[T]
27
28
  | Callable[..., T]
28
29
  | Callable[..., Awaitable[T]]
29
- | Iterable[TypeInfo[T]]
30
+ | Sequence[TypeInfo[T]]
30
31
  )
31
32
 
32
33
 
@@ -50,7 +50,7 @@ from injection._core.common.asynchronous import (
50
50
  from injection._core.common.event import Event, EventChannel, EventListener
51
51
  from injection._core.common.invertible import Invertible, SimpleInvertible
52
52
  from injection._core.common.key import new_short_key
53
- from injection._core.common.lazy import Lazy, lazy
53
+ from injection._core.common.lazy import Lazy, alazy, lazy
54
54
  from injection._core.common.threading import get_lock
55
55
  from injection._core.common.type import (
56
56
  InputType,
@@ -512,9 +512,9 @@ class Module(Broker, EventListener):
512
512
  mode: Mode | ModeStr = Mode.get_default(),
513
513
  ) -> Any:
514
514
  def decorator(wp: Recipe[P, T]) -> Recipe[P, T]:
515
- lazy_instance = lazy(wp)
515
+ recipe: Recipe[[], T] = alazy(wp) if iscoroutinefunction(wp) else lazy(wp) # type: ignore[arg-type]
516
516
  self.injectable(
517
- lambda: ~lazy_instance,
517
+ recipe,
518
518
  ignore_type_hint=True,
519
519
  inject=False,
520
520
  on=(wp, on),
@@ -22,9 +22,20 @@ type EntrypointSetupMethod[**P, **EPP, T1, T2] = Callable[
22
22
  ]
23
23
 
24
24
 
25
- def autocall[**P, T](wrapped: Callable[P, T] | None = None, /) -> Any:
26
- def decorator(wp: Callable[P, T]) -> Callable[P, T]:
27
- wp() # type: ignore[call-arg]
25
+ @overload
26
+ def autocall[T: Callable[..., Any]](wrapped: T, /) -> T: ...
27
+
28
+
29
+ @overload
30
+ def autocall[T: Callable[..., Any]](wrapped: None = ..., /) -> Callable[[T], T]: ...
31
+
32
+
33
+ def autocall[T: Callable[..., Any]](
34
+ wrapped: T | None = None,
35
+ /,
36
+ ) -> T | Callable[[T], T]:
37
+ def decorator(wp: T) -> T:
38
+ wp()
28
39
  return wp
29
40
 
30
41
  return decorator(wrapped) if wrapped else decorator
@@ -30,7 +30,7 @@ test = [
30
30
 
31
31
  [project]
32
32
  name = "python-injection"
33
- version = "0.19.3"
33
+ version = "0.19.5"
34
34
  description = "Fast and easy dependency injection framework."
35
35
  license = "MIT"
36
36
  license-files = ["LICENSE"]
@@ -1,41 +0,0 @@
1
- from collections.abc import Callable, Iterator
2
- from functools import partial
3
-
4
- from injection._core.common.invertible import Invertible, SimpleInvertible
5
-
6
-
7
- def lazy[T](factory: Callable[..., T]) -> Invertible[T]:
8
- def cache() -> Iterator[T]:
9
- nonlocal factory
10
- value = factory()
11
- del factory
12
-
13
- while True:
14
- yield value
15
-
16
- getter = partial(next, cache())
17
- return SimpleInvertible(getter)
18
-
19
-
20
- class Lazy[T](Invertible[T]):
21
- __slots__ = ("__invertible", "__is_set")
22
-
23
- __invertible: Invertible[T]
24
- __is_set: bool
25
-
26
- def __init__(self, factory: Callable[..., T]) -> None:
27
- @lazy
28
- def invertible() -> T:
29
- value = factory()
30
- self.__is_set = True
31
- return value
32
-
33
- self.__invertible = invertible
34
- self.__is_set = False
35
-
36
- def __invert__(self) -> T:
37
- return ~self.__invertible
38
-
39
- @property
40
- def is_set(self) -> bool:
41
- return self.__is_set