python-injection 0.12.0__tar.gz → 0.12.1.post0__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 (24) hide show
  1. {python_injection-0.12.0 → python_injection-0.12.1.post0}/PKG-INFO +1 -1
  2. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/asynchronous.py +1 -6
  3. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/invertible.py +1 -2
  4. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/lazy.py +0 -5
  5. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/injectables.py +1 -9
  6. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/module.py +23 -55
  7. {python_injection-0.12.0 → python_injection-0.12.1.post0}/pyproject.toml +1 -1
  8. {python_injection-0.12.0 → python_injection-0.12.1.post0}/README.md +0 -0
  9. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/__init__.py +0 -0
  10. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/__init__.pyi +0 -0
  11. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/__init__.py +0 -0
  12. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/__init__.py +0 -0
  13. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/event.py +0 -0
  14. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/threading.py +0 -0
  15. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/common/type.py +0 -0
  16. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/descriptors.py +0 -0
  17. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/_core/hook.py +0 -0
  18. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/exceptions.py +0 -0
  19. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/integrations/__init__.py +0 -0
  20. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/integrations/fastapi.py +0 -0
  21. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/py.typed +0 -0
  22. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/testing/__init__.py +0 -0
  23. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/testing/__init__.pyi +0 -0
  24. {python_injection-0.12.0 → python_injection-0.12.1.post0}/injection/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python-injection
3
- Version: 0.12.0
3
+ Version: 0.12.1.post0
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
@@ -1,14 +1,13 @@
1
1
  from abc import abstractmethod
2
2
  from collections.abc import Awaitable, Callable, Generator
3
3
  from dataclasses import dataclass
4
- from typing import Any, NoReturn, Protocol, override, runtime_checkable
4
+ from typing import Any, NoReturn, Protocol, runtime_checkable
5
5
 
6
6
 
7
7
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
8
8
  class SimpleAwaitable[T](Awaitable[T]):
9
9
  callable: Callable[..., Awaitable[T]]
10
10
 
11
- @override
12
11
  def __await__(self) -> Generator[Any, Any, T]:
13
12
  return self.callable().__await__()
14
13
 
@@ -30,11 +29,9 @@ class Caller[**P, T](Protocol):
30
29
  class AsyncCaller[**P, T](Caller[P, T]):
31
30
  callable: Callable[P, Awaitable[T]]
32
31
 
33
- @override
34
32
  async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
35
33
  return await self.callable(*args, **kwargs)
36
34
 
37
- @override
38
35
  def call(self, /, *args: P.args, **kwargs: P.kwargs) -> NoReturn:
39
36
  raise RuntimeError(
40
37
  "Synchronous call isn't supported for an asynchronous Callable."
@@ -45,10 +42,8 @@ class AsyncCaller[**P, T](Caller[P, T]):
45
42
  class SyncCaller[**P, T](Caller[P, T]):
46
43
  callable: Callable[P, T]
47
44
 
48
- @override
49
45
  async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
50
46
  return self.callable(*args, **kwargs)
51
47
 
52
- @override
53
48
  def call(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
54
49
  return self.callable(*args, **kwargs)
@@ -1,7 +1,7 @@
1
1
  from abc import abstractmethod
2
2
  from collections.abc import Callable
3
3
  from dataclasses import dataclass
4
- from typing import Protocol, override, runtime_checkable
4
+ from typing import Protocol, runtime_checkable
5
5
 
6
6
 
7
7
  @runtime_checkable
@@ -15,6 +15,5 @@ class Invertible[T](Protocol):
15
15
  class SimpleInvertible[T](Invertible[T]):
16
16
  callable: Callable[..., T]
17
17
 
18
- @override
19
18
  def __invert__(self) -> T:
20
19
  return self.callable()
@@ -1,6 +1,5 @@
1
1
  from collections.abc import Callable, Iterator, Mapping
2
2
  from types import MappingProxyType
3
- from typing import override
4
3
 
5
4
  from injection._core.common.invertible import Invertible
6
5
 
@@ -14,7 +13,6 @@ class Lazy[T](Invertible[T]):
14
13
  def __init__(self, factory: Callable[..., T]) -> None:
15
14
  self.__setup_cache(factory)
16
15
 
17
- @override
18
16
  def __invert__(self) -> T:
19
17
  return next(self.__iterator)
20
18
 
@@ -44,15 +42,12 @@ class LazyMapping[K, V](Mapping[K, V]):
44
42
  def __init__(self, iterator: Iterator[tuple[K, V]]) -> None:
45
43
  self.__lazy = Lazy(lambda: MappingProxyType(dict(iterator)))
46
44
 
47
- @override
48
45
  def __getitem__(self, key: K, /) -> V:
49
46
  return (~self.__lazy)[key]
50
47
 
51
- @override
52
48
  def __iter__(self) -> Iterator[K]:
53
49
  yield from ~self.__lazy
54
50
 
55
- @override
56
51
  def __len__(self) -> int:
57
52
  return len(~self.__lazy)
58
53
 
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
2
2
  from collections.abc import MutableMapping
3
3
  from contextlib import suppress
4
4
  from dataclasses import dataclass
5
- from typing import Any, ClassVar, NoReturn, Protocol, override, runtime_checkable
5
+ from typing import Any, ClassVar, NoReturn, Protocol, runtime_checkable
6
6
 
7
7
  from injection._core.common.asynchronous import Caller
8
8
  from injection._core.common.threading import synchronized
@@ -37,11 +37,9 @@ class BaseInjectable[T](Injectable[T], ABC):
37
37
  class SimpleInjectable[T](BaseInjectable[T]):
38
38
  __slots__ = ()
39
39
 
40
- @override
41
40
  async def aget_instance(self) -> T:
42
41
  return await self.factory.acall()
43
42
 
44
- @override
45
43
  def get_instance(self) -> T:
46
44
  return self.factory.call()
47
45
 
@@ -56,15 +54,12 @@ class SingletonInjectable[T](BaseInjectable[T]):
56
54
  return self.__dict__
57
55
 
58
56
  @property
59
- @override
60
57
  def is_locked(self) -> bool:
61
58
  return self.__key in self.cache
62
59
 
63
- @override
64
60
  def unlock(self) -> None:
65
61
  self.cache.clear()
66
62
 
67
- @override
68
63
  async def aget_instance(self) -> T:
69
64
  with suppress(KeyError):
70
65
  return self.__check_instance()
@@ -75,7 +70,6 @@ class SingletonInjectable[T](BaseInjectable[T]):
75
70
 
76
71
  return instance
77
72
 
78
- @override
79
73
  def get_instance(self) -> T:
80
74
  with suppress(KeyError):
81
75
  return self.__check_instance()
@@ -97,10 +91,8 @@ class SingletonInjectable[T](BaseInjectable[T]):
97
91
  class ShouldBeInjectable[T](Injectable[T]):
98
92
  cls: type[T]
99
93
 
100
- @override
101
94
  async def aget_instance(self) -> T:
102
95
  return self.get_instance()
103
96
 
104
- @override
105
97
  def get_instance(self) -> NoReturn:
106
98
  raise InjectionError(f"`{self.cls}` should be an injectable.")
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- import inspect
5
4
  from abc import ABC, abstractmethod
6
5
  from collections import OrderedDict
7
6
  from collections.abc import (
@@ -17,7 +16,8 @@ from contextlib import contextmanager, suppress
17
16
  from dataclasses import dataclass, field
18
17
  from enum import StrEnum
19
18
  from functools import partialmethod, singledispatchmethod, update_wrapper
20
- from inspect import Signature, isclass, iscoroutinefunction
19
+ from inspect import Signature, isclass, iscoroutinefunction, markcoroutinefunction
20
+ from inspect import signature as inspect_signature
21
21
  from logging import Logger, getLogger
22
22
  from queue import Empty, Queue
23
23
  from types import MethodType
@@ -29,9 +29,7 @@ from typing import (
29
29
  NamedTuple,
30
30
  Protocol,
31
31
  Self,
32
- TypeGuard,
33
32
  overload,
34
- override,
35
33
  runtime_checkable,
36
34
  )
37
35
  from uuid import uuid4
@@ -76,7 +74,6 @@ class LocatorDependenciesUpdated[T](LocatorEvent):
76
74
  classes: Collection[InputType[T]]
77
75
  mode: Mode
78
76
 
79
- @override
80
77
  def __str__(self) -> str:
81
78
  length = len(self.classes)
82
79
  formatted_types = ", ".join(f"`{cls}`" for cls in self.classes)
@@ -95,7 +92,6 @@ class ModuleEvent(Event, ABC):
95
92
  class ModuleEventProxy(ModuleEvent):
96
93
  event: Event
97
94
 
98
- @override
99
95
  def __str__(self) -> str:
100
96
  return f"`{self.module}` has propagated an event: {self.origin}"
101
97
 
@@ -116,7 +112,6 @@ class ModuleAdded(ModuleEvent):
116
112
  module_added: Module
117
113
  priority: Priority
118
114
 
119
- @override
120
115
  def __str__(self) -> str:
121
116
  return f"`{self.module}` now uses `{self.module_added}`."
122
117
 
@@ -125,7 +120,6 @@ class ModuleAdded(ModuleEvent):
125
120
  class ModuleRemoved(ModuleEvent):
126
121
  module_removed: Module
127
122
 
128
- @override
129
123
  def __str__(self) -> str:
130
124
  return f"`{self.module}` no longer uses `{self.module_removed}`."
131
125
 
@@ -135,7 +129,6 @@ class ModulePriorityUpdated(ModuleEvent):
135
129
  module_updated: Module
136
130
  priority: Priority
137
131
 
138
- @override
139
132
  def __str__(self) -> str:
140
133
  return (
141
134
  f"In `{self.module}`, the priority `{self.priority}` "
@@ -215,18 +208,20 @@ class Updater[T]:
215
208
  return Record(injectable, self.mode)
216
209
 
217
210
 
218
- class LocatorHooks[T](NamedTuple):
219
- on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool]
220
- on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]]
221
- on_update: Hook[[Updater[T]], Updater[T]]
222
-
223
- @classmethod
224
- def default(cls) -> Self:
225
- return cls(
226
- on_conflict=Hook(),
227
- on_input=Hook(),
228
- on_update=Hook(),
229
- )
211
+ @dataclass(repr=False, eq=False, frozen=True, slots=True)
212
+ class LocatorHooks[T]:
213
+ on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool] = field(
214
+ default_factory=Hook,
215
+ init=False,
216
+ )
217
+ on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]] = field(
218
+ default_factory=Hook,
219
+ init=False,
220
+ )
221
+ on_update: Hook[[Updater[T]], Updater[T]] = field(
222
+ default_factory=Hook,
223
+ init=False,
224
+ )
230
225
 
231
226
 
232
227
  @dataclass(repr=False, frozen=True, slots=True)
@@ -240,9 +235,8 @@ class Locator(Broker):
240
235
  init=False,
241
236
  )
242
237
 
243
- static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks.default()
238
+ static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks()
244
239
 
245
- @override
246
240
  def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
247
241
  for input_class in self.__standardize_inputs((cls,)):
248
242
  try:
@@ -254,7 +248,6 @@ class Locator(Broker):
254
248
 
255
249
  raise NoInjectable(cls)
256
250
 
257
- @override
258
251
  def __contains__(self, cls: InputType[Any], /) -> bool:
259
252
  return any(
260
253
  input_class in self.__records
@@ -262,7 +255,6 @@ class Locator(Broker):
262
255
  )
263
256
 
264
257
  @property
265
- @override
266
258
  def is_locked(self) -> bool:
267
259
  return any(injectable.is_locked for injectable in self.__injectables)
268
260
 
@@ -284,7 +276,6 @@ class Locator(Broker):
284
276
 
285
277
  return self
286
278
 
287
- @override
288
279
  @synchronized()
289
280
  def unlock(self) -> Self:
290
281
  for injectable in self.__injectables:
@@ -292,7 +283,6 @@ class Locator(Broker):
292
283
 
293
284
  return self
294
285
 
295
- @override
296
286
  async def all_ready(self) -> None:
297
287
  for injectable in self.__injectables:
298
288
  await injectable.aget_instance()
@@ -387,7 +377,6 @@ class Module(Broker, EventListener):
387
377
  def __post_init__(self) -> None:
388
378
  self.__locator.add_listener(self)
389
379
 
390
- @override
391
380
  def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
392
381
  for broker in self.__brokers:
393
382
  with suppress(KeyError):
@@ -395,12 +384,10 @@ class Module(Broker, EventListener):
395
384
 
396
385
  raise NoInjectable(cls)
397
386
 
398
- @override
399
387
  def __contains__(self, cls: InputType[Any], /) -> bool:
400
388
  return any(cls in broker for broker in self.__brokers)
401
389
 
402
390
  @property
403
- @override
404
391
  def is_locked(self) -> bool:
405
392
  return any(broker.is_locked for broker in self.__brokers)
406
393
 
@@ -695,7 +682,6 @@ class Module(Broker, EventListener):
695
682
 
696
683
  return self
697
684
 
698
- @override
699
685
  @synchronized()
700
686
  def unlock(self) -> Self:
701
687
  for broker in self.__brokers:
@@ -703,7 +689,6 @@ class Module(Broker, EventListener):
703
689
 
704
690
  return self
705
691
 
706
- @override
707
692
  async def all_ready(self) -> None:
708
693
  for broker in self.__brokers:
709
694
  await broker.all_ready()
@@ -720,7 +705,6 @@ class Module(Broker, EventListener):
720
705
  self.__channel.remove_listener(listener)
721
706
  return self
722
707
 
723
- @override
724
708
  def on_event(self, event: Event, /) -> ContextManager[None] | None:
725
709
  self_event = ModuleEventProxy(self, event)
726
710
  return self.dispatch(self_event)
@@ -890,7 +874,7 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
890
874
  return self.__signature
891
875
 
892
876
  with synchronized():
893
- signature = inspect.signature(self.wrapped, eval_str=True)
877
+ signature = inspect_signature(self.wrapped, eval_str=True)
894
878
  self.__signature = signature
895
879
 
896
880
  return signature
@@ -915,13 +899,11 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
915
899
  additional_arguments = self.__dependencies.get_arguments()
916
900
  return self.__bind(args, kwargs, additional_arguments)
917
901
 
918
- @override
919
902
  async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
920
903
  self.__setup()
921
904
  arguments = await self.abind(args, kwargs)
922
905
  return self.wrapped(*arguments.args, **arguments.kwargs)
923
906
 
924
- @override
925
907
  def call(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
926
908
  self.__setup()
927
909
  arguments = self.bind(args, kwargs)
@@ -957,7 +939,6 @@ class InjectMetadata[**P, T](Caller[P, T], EventListener):
957
939
  return decorator(wrapped) if wrapped else decorator
958
940
 
959
941
  @singledispatchmethod
960
- @override
961
942
  def on_event(self, event: Event, /) -> ContextManager[None] | None: # type: ignore[override]
962
943
  return None
963
944
 
@@ -1014,11 +995,9 @@ class InjectedFunction[**P, T](ABC):
1014
995
  update_wrapper(self, metadata.wrapped)
1015
996
  self.__inject_metadata__ = metadata
1016
997
 
1017
- @override
1018
998
  def __repr__(self) -> str: # pragma: no cover
1019
999
  return repr(self.__inject_metadata__.wrapped)
1020
1000
 
1021
- @override
1022
1001
  def __str__(self) -> str: # pragma: no cover
1023
1002
  return str(self.__inject_metadata__.wrapped)
1024
1003
 
@@ -1043,7 +1022,10 @@ class InjectedFunction[**P, T](ABC):
1043
1022
  class AsyncInjectedFunction[**P, T](InjectedFunction[P, Awaitable[T]]):
1044
1023
  __slots__ = ()
1045
1024
 
1046
- @override
1025
+ def __init__(self, metadata: InjectMetadata[P, Awaitable[T]]) -> None:
1026
+ super().__init__(metadata)
1027
+ markcoroutinefunction(self)
1028
+
1047
1029
  async def __call__(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
1048
1030
  return await (await self.__inject_metadata__.acall(*args, **kwargs))
1049
1031
 
@@ -1051,26 +1033,12 @@ class AsyncInjectedFunction[**P, T](InjectedFunction[P, Awaitable[T]]):
1051
1033
  class SyncInjectedFunction[**P, T](InjectedFunction[P, T]):
1052
1034
  __slots__ = ()
1053
1035
 
1054
- @override
1055
1036
  def __call__(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
1056
1037
  return self.__inject_metadata__.call(*args, **kwargs)
1057
1038
 
1058
1039
 
1059
- def _is_coroutine_function[**P, T](
1060
- function: Callable[P, T] | Callable[P, Awaitable[T]],
1061
- ) -> TypeGuard[Callable[P, Awaitable[T]]]:
1062
- if iscoroutinefunction(function):
1063
- return True
1064
-
1065
- elif isclass(function):
1066
- return False
1067
-
1068
- call = getattr(function, "__call__", None)
1069
- return iscoroutinefunction(call)
1070
-
1071
-
1072
1040
  def _get_caller[**P, T](function: Callable[P, T]) -> Caller[P, T]:
1073
- if _is_coroutine_function(function):
1041
+ if iscoroutinefunction(function):
1074
1042
  return AsyncCaller(function)
1075
1043
 
1076
1044
  elif isinstance(function, InjectedFunction):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-injection"
3
- version = "0.12.0"
3
+ version = "0.12.1.post0"
4
4
  description = "Fast and easy dependency injection framework."
5
5
  license = "MIT"
6
6
  readme = "README.md"