python-injection 0.19.2__py3-none-any.whl → 0.19.4__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/__init__.pyi CHANGED
@@ -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,39 +136,127 @@ 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[**P, T](
149
+ self,
150
+ wrapped: None = ...,
151
+ /,
152
+ *,
153
+ threadsafe: bool | None = ...,
154
+ ) -> _Decorator[Callable[P, T]] | _Decorator[type[T]]: ...
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[**P, T](
196
+ self,
197
+ wrapped: None = ...,
198
+ /,
199
+ *,
200
+ cls: _InjectableFactory[T] = ...,
201
+ inject: bool = ...,
202
+ on: _TypeInfo[T] = ...,
203
+ mode: Mode | ModeStr = ...,
204
+ ) -> (
205
+ _Decorator[Callable[P, T]]
206
+ | _Decorator[Callable[P, Awaitable[T]]]
207
+ | _Decorator[type[T]]
208
+ ): ...
209
+ @overload
154
210
  def singleton[**P, T](
155
211
  self,
156
- wrapped: _Recipe[P, T] = ...,
212
+ wrapped: Callable[P, T],
157
213
  /,
158
214
  *,
159
215
  inject: bool = ...,
160
216
  on: _TypeInfo[T] = ...,
161
217
  mode: Mode | ModeStr = ...,
162
- ) -> Any:
218
+ ) -> Callable[P, T]:
163
219
  """
164
220
  Decorator applicable to a class or function. It is used to indicate how the
165
221
  singleton will be constructed. At injection time, the injected instance will
166
222
  always be the same.
167
223
  """
168
224
 
169
- def scoped[T](
225
+ @overload
226
+ def singleton[**P, T]( # type: ignore[overload-overlap]
227
+ self,
228
+ wrapped: Callable[P, Awaitable[T]],
229
+ /,
230
+ *,
231
+ inject: bool = ...,
232
+ on: _TypeInfo[T] = ...,
233
+ mode: Mode | ModeStr = ...,
234
+ ) -> Callable[P, Awaitable[T]]: ...
235
+ @overload
236
+ def singleton[T](
237
+ self,
238
+ wrapped: type[T],
239
+ /,
240
+ *,
241
+ inject: bool = ...,
242
+ on: _TypeInfo[T] = ...,
243
+ mode: Mode | ModeStr = ...,
244
+ ) -> type[T]: ...
245
+ @overload
246
+ def singleton[**P, T](
247
+ self,
248
+ wrapped: None = ...,
249
+ /,
250
+ *,
251
+ inject: bool = ...,
252
+ on: _TypeInfo[T] = ...,
253
+ mode: Mode | ModeStr = ...,
254
+ ) -> (
255
+ _Decorator[Callable[P, T]]
256
+ | _Decorator[Callable[P, Awaitable[T]]]
257
+ | _Decorator[type[T]]
258
+ ): ...
259
+ def scoped[**P, T](
170
260
  self,
171
261
  scope_name: str,
172
262
  /,
@@ -174,34 +264,79 @@ class Module:
174
264
  inject: bool = ...,
175
265
  on: _TypeInfo[T] = (),
176
266
  mode: Mode | ModeStr = ...,
177
- ) -> Any:
267
+ ) -> (
268
+ _Decorator[Callable[P, T]]
269
+ | _Decorator[Callable[P, Awaitable[T]]]
270
+ | _Decorator[Callable[P, AsyncIterator[T]]]
271
+ | _Decorator[Callable[P, Iterator[T]]]
272
+ | _Decorator[type[T]]
273
+ ):
178
274
  """
179
275
  Decorator applicable to a class or function or generator function. It is used
180
276
  to indicate how the scoped instance will be constructed. At injection time, the
181
277
  injected instance is retrieved from the scope.
182
278
  """
183
279
 
184
- def should_be_injectable[T](self, wrapped: type[T] = ..., /) -> Any:
280
+ @overload
281
+ def should_be_injectable[T](self, wrapped: type[T], /) -> type[T]:
185
282
  """
186
283
  Decorator applicable to a class. It is used to specify whether an injectable
187
284
  should be registered. Raise an exception at injection time if the class isn't
188
285
  registered.
189
286
  """
190
287
 
288
+ @overload
289
+ def should_be_injectable[T](
290
+ self,
291
+ wrapped: None = ...,
292
+ /,
293
+ ) -> _Decorator[type[T]]: ...
294
+ @overload
191
295
  def constant[**P, T](
192
296
  self,
193
- wrapped: _Recipe[P, T] = ...,
297
+ wrapped: Callable[P, T],
194
298
  /,
195
299
  *,
196
300
  on: _TypeInfo[T] = ...,
197
301
  mode: Mode | ModeStr = ...,
198
- ) -> Any:
302
+ ) -> Callable[P, T]:
199
303
  """
200
304
  Decorator applicable to a class or function. It is used to indicate how the
201
305
  constant is constructed. At injection time, the injected instance will always
202
306
  be the same. Unlike `@singleton`, dependencies will not be resolved.
203
307
  """
204
308
 
309
+ @overload
310
+ def constant[**P, T]( # type: ignore[overload-overlap]
311
+ self,
312
+ wrapped: Callable[P, Awaitable[T]],
313
+ /,
314
+ *,
315
+ on: _TypeInfo[T] = ...,
316
+ mode: Mode | ModeStr = ...,
317
+ ) -> Callable[P, Awaitable[T]]: ...
318
+ @overload
319
+ def constant[T](
320
+ self,
321
+ wrapped: type[T],
322
+ /,
323
+ *,
324
+ on: _TypeInfo[T] = ...,
325
+ mode: Mode | ModeStr = ...,
326
+ ) -> type[T]: ...
327
+ @overload
328
+ def constant[**P, T](
329
+ self,
330
+ wrapped: None = ...,
331
+ /,
332
+ *,
333
+ on: _TypeInfo[T] = ...,
334
+ mode: Mode | ModeStr = ...,
335
+ ) -> (
336
+ _Decorator[Callable[P, T]]
337
+ | _Decorator[Callable[P, Awaitable[T]]]
338
+ | _Decorator[type[T]]
339
+ ): ...
205
340
  def set_constant[T](
206
341
  self,
207
342
  instance: T,
@@ -1,41 +1,50 @@
1
- from collections.abc import Callable, Iterator
1
+ from collections.abc import AsyncIterator, Awaitable, Callable, Iterator
2
2
  from functools import partial
3
3
 
4
- from injection._core.common.invertible import Invertible, SimpleInvertible
4
+ from injection._core.common.invertible import Invertible
5
5
 
6
6
 
7
- def lazy[T](factory: Callable[..., T]) -> Invertible[T]:
7
+ def lazy[T](factory: Callable[..., T]) -> Callable[[], T]:
8
8
  def cache() -> Iterator[T]:
9
- nonlocal factory
10
9
  value = factory()
11
- del factory
10
+ while True:
11
+ yield value
12
+
13
+ return partial(next, cache())
12
14
 
15
+
16
+ def alazy[T](factory: Callable[..., Awaitable[T]]) -> Callable[[], Awaitable[T]]:
17
+ async def cache() -> AsyncIterator[T]:
18
+ value = await factory()
13
19
  while True:
14
20
  yield value
15
21
 
16
- getter = partial(next, cache())
17
- return SimpleInvertible(getter)
22
+ return partial(_anext, cache())
18
23
 
19
24
 
20
25
  class Lazy[T](Invertible[T]):
21
- __slots__ = ("__invertible", "__is_set")
26
+ __slots__ = ("__get", "__is_set")
22
27
 
23
- __invertible: Invertible[T]
28
+ __get: Callable[[], T]
24
29
  __is_set: bool
25
30
 
26
31
  def __init__(self, factory: Callable[..., T]) -> None:
27
32
  @lazy
28
- def invertible() -> T:
33
+ def get() -> T:
29
34
  value = factory()
30
35
  self.__is_set = True
31
36
  return value
32
37
 
33
- self.__invertible = invertible
38
+ self.__get = get
34
39
  self.__is_set = False
35
40
 
36
41
  def __invert__(self) -> T:
37
- return ~self.__invertible
42
+ return self.__get()
38
43
 
39
44
  @property
40
45
  def is_set(self) -> bool:
41
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
 
@@ -89,8 +90,16 @@ def standardize_types(
89
90
  else:
90
91
  yield tp
91
92
 
92
- if with_origin and origin is not None:
93
- yield origin
93
+ if with_origin:
94
+ if origin is not None:
95
+ yield origin
96
+
97
+ for alias in (tp, origin):
98
+ if isinstance(alias, TypeAliasType):
99
+ yield from standardize_types(
100
+ alias.__value__,
101
+ with_origin=with_origin,
102
+ )
94
103
 
95
104
  continue
96
105
 
injection/_core/module.py CHANGED
@@ -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,
@@ -347,8 +347,8 @@ class Locator(Broker):
347
347
  @staticmethod
348
348
  def __standardize_inputs[T](
349
349
  classes: Iterable[InputType[T]],
350
- ) -> Iterable[InputType[T]]:
351
- return tuple(standardize_types(*classes, with_origin=True))
350
+ ) -> Iterator[InputType[T]]:
351
+ return standardize_types(*classes, with_origin=True)
352
352
 
353
353
  @staticmethod
354
354
  def __update_preprocessing[T](updater: Updater[T]) -> Updater[T]:
@@ -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),
injection/entrypoint.py CHANGED
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-injection
3
- Version: 0.19.2
3
+ Version: 0.19.4
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Project-URL: Repository, https://github.com/100nm/python-injection
6
6
  Author: remimd
@@ -1,6 +1,6 @@
1
1
  injection/__init__.py,sha256=iJm0BbyGZw-Qr5e8d2C3n8-7FiVD-sy4LU_i_n3AgHY,1318
2
- injection/__init__.pyi,sha256=2ndBULZyjN0SnyRml2gba9OOsTY0BhR3STEyvv1aZOA,11566
3
- injection/entrypoint.py,sha256=NIILL_w3z2JKyn7S9XXwE0JtH2icuDWnAVpUY1fAMf8,4805
2
+ injection/__init__.pyi,sha256=VCuJkbE1S2XppeTkwiDAbOsVBmlmCpFFXe5ztTUb_-Q,14942
3
+ injection/entrypoint.py,sha256=1JtooUCE9nIvHGAps5ypRb9ZEbgLdLwydkGF-kXMXDY,4953
4
4
  injection/exceptions.py,sha256=v57yMujiq6H_zwwn30A8UYEZX9R9k-bY8FnsdaimPM4,1025
5
5
  injection/loaders.py,sha256=gKlJfe9nXCuB8r6j0RF9_2FHC6YplM8GQYsgRqyxYw8,7257
6
6
  injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -8,7 +8,7 @@ injection/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  injection/_core/asfunction.py,sha256=fTgAAWsDWUz89kYsoSVDXdqYKIuh6HtUW5MohGp3ov4,1767
9
9
  injection/_core/descriptors.py,sha256=1OX6JnM8Ux14vW1JSW3FzPgKc2VMTKqJUYBGT3Ypafg,800
10
10
  injection/_core/injectables.py,sha256=fxhiGv7qTCbUunhhd6a3ahosFmgznUFsEvqlwxi4gS4,6098
11
- injection/_core/module.py,sha256=T9zvSOjMaPZiC_DCV7BIKOqCrmAHcYcleqgNro0MBgU,32624
11
+ injection/_core/module.py,sha256=IrNpWIO75kO3REQX6RdQdtZDjc-S17B8Y2KdM_NGacA,32684
12
12
  injection/_core/scope.py,sha256=r094k1Vjvwm0hTf7AQGYrxxvqQgb7_CDVUKaHQ8wyeM,8772
13
13
  injection/_core/slots.py,sha256=g9TG6CbqRzCsjg01iPyfRtTTUCJnnJOwcj9mJabH0dc,37
14
14
  injection/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -16,15 +16,15 @@ injection/_core/common/asynchronous.py,sha256=nKY2_PAMFF2haC75Fwp8O9Zd-SDuenE6n3
16
16
  injection/_core/common/event.py,sha256=XjzV8gxtGlGvzZs_ykvoC60qmdpd3RN08Eiqz5QUwes,1236
17
17
  injection/_core/common/invertible.py,sha256=gA_vw5nBjgp_w9MrDK5jMO8lhuOQWON8BbPpKzEuIY0,502
18
18
  injection/_core/common/key.py,sha256=ghkZD-Y8Moz6SEPNgMh3xgsZUjDVq-XYAmXaCu5VuCA,80
19
- injection/_core/common/lazy.py,sha256=L7C2dB5UBI--W5Kkvntp_jypYhudY3SHqs8rM6jxxsk,965
19
+ injection/_core/common/lazy.py,sha256=hZvz9LhlYxVkD_D8VBAvQmy7YuVaaw075jq0XM0w9_Y,1193
20
20
  injection/_core/common/threading.py,sha256=kwRXNa9ocndIqeZA9kMHjEa8SBpHFcJARj1bgrWCpxE,225
21
- injection/_core/common/type.py,sha256=SCDtmBv9qFvEf5o5tTgCuwMDfuo1fgjSW0bUqA8ACis,2251
21
+ injection/_core/common/type.py,sha256=mmDMaR68pQpwGnOLLkOmy9slCvgjLVYuEhoYVyANRlk,2564
22
22
  injection/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  injection/ext/fastapi.py,sha256=fiy3-mZIIwGcql3Y5ekFX8_7hALzqXP5u40qbtNE73o,1441
24
24
  injection/ext/fastapi.pyi,sha256=HLs7mfruIEFRrN_Xf8oCvSa4qwHWfwm6HHU_KMedXkE,185
25
25
  injection/testing/__init__.py,sha256=bJ7WXBXrw4rHc91AFVFnOwFLWOlpvX9Oh2SnRQ_NESo,919
26
26
  injection/testing/__init__.pyi,sha256=raGsGlxwbz3jkzJwA_5oCIE1emWINjT2UuwzbnqRb-0,577
27
- python_injection-0.19.2.dist-info/METADATA,sha256=92VOjBIEVr3f-V35vtchT60StdudDnupyvXgAx1qkxE,4301
28
- python_injection-0.19.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- python_injection-0.19.2.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
30
- python_injection-0.19.2.dist-info/RECORD,,
27
+ python_injection-0.19.4.dist-info/METADATA,sha256=xtDdgHy2s2fYA8jwKObxTd--xD2gC6yPVkDNKSwgr8c,4301
28
+ python_injection-0.19.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ python_injection-0.19.4.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
30
+ python_injection-0.19.4.dist-info/RECORD,,