python-injection 0.8.5__py3-none-any.whl → 0.9.1__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__.py CHANGED
@@ -7,7 +7,6 @@ __all__ = (
7
7
  "InjectableMode",
8
8
  "Module",
9
9
  "ModulePriority",
10
- "default_module",
11
10
  "get_instance",
12
11
  "get_lazy_instance",
13
12
  "inject",
@@ -17,12 +16,14 @@ __all__ = (
17
16
  "singleton",
18
17
  )
19
18
 
20
- default_module = Module(f"{__name__}:default_module")
19
+ _module = Module.default()
21
20
 
22
- get_instance = default_module.get_instance
23
- get_lazy_instance = default_module.get_lazy_instance
24
- inject = default_module.inject
25
- injectable = default_module.injectable
26
- set_constant = default_module.set_constant
27
- should_be_injectable = default_module.should_be_injectable
28
- singleton = default_module.singleton
21
+ get_instance = _module.get_instance
22
+ get_lazy_instance = _module.get_lazy_instance
23
+ inject = _module.inject
24
+ injectable = _module.injectable
25
+ set_constant = _module.set_constant
26
+ should_be_injectable = _module.should_be_injectable
27
+ singleton = _module.singleton
28
+
29
+ del _module
injection/__init__.pyi CHANGED
@@ -1,33 +1,34 @@
1
1
  from abc import abstractmethod
2
- from collections.abc import Callable, Iterable
2
+ from collections.abc import Callable
3
3
  from contextlib import ContextDecorator
4
- from enum import Enum
4
+ from enum import StrEnum
5
5
  from types import UnionType
6
6
  from typing import (
7
7
  Any,
8
8
  ContextManager,
9
- Final,
10
- Literal,
11
9
  Protocol,
12
- TypeVar,
10
+ Self,
13
11
  final,
14
12
  runtime_checkable,
15
13
  )
16
14
 
17
15
  from .common.invertible import Invertible
16
+ from .common.tools.type import TypeInfo
17
+ from .core import InjectableFactory
18
+ from .core import ModeStr as InjectableModeStr
19
+ from .core import PriorityStr as ModulePriorityStr
18
20
 
19
- _T = TypeVar("_T")
20
- _T_co = TypeVar("_T_co", covariant=True)
21
+ _module: Module = ...
21
22
 
22
- default_module: Final[Module] = ...
23
+ get_instance = _module.get_instance
24
+ get_lazy_instance = _module.get_lazy_instance
25
+ inject = _module.inject
26
+ injectable = _module.injectable
27
+ set_constant = _module.set_constant
28
+ should_be_injectable = _module.should_be_injectable
29
+ singleton = _module.singleton
23
30
 
24
- get_instance = default_module.get_instance
25
- get_lazy_instance = default_module.get_lazy_instance
26
- inject = default_module.inject
27
- injectable = default_module.injectable
28
- set_constant = default_module.set_constant
29
- should_be_injectable = default_module.should_be_injectable
30
- singleton = default_module.singleton
31
+ del _module
31
32
 
32
33
  @final
33
34
  class Module:
@@ -41,6 +42,8 @@ class Module:
41
42
 
42
43
  def __init__(self, name: str = ...): ...
43
44
  def __contains__(self, cls: type | UnionType, /) -> bool: ...
45
+ @property
46
+ def is_locked(self) -> bool: ...
44
47
  def inject(self, wrapped: Callable[..., Any] = ..., /):
45
48
  """
46
49
  Decorator applicable to a class or function. Inject function dependencies using
@@ -48,15 +51,15 @@ class Module:
48
51
  will be those of the `__init__` method.
49
52
  """
50
53
 
51
- def injectable(
54
+ def injectable[T](
52
55
  self,
53
- wrapped: Callable[..., Any] = ...,
56
+ wrapped: Callable[..., T] = ...,
54
57
  /,
55
58
  *,
56
- cls: type[Injectable] = ...,
59
+ cls: InjectableFactory[T] = ...,
57
60
  inject: bool = ...,
58
- on: type | Iterable[type] | UnionType = ...,
59
- mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
61
+ on: TypeInfo[T] = ...,
62
+ mode: InjectableMode | InjectableModeStr = ...,
60
63
  ):
61
64
  """
62
65
  Decorator applicable to a class or function. It is used to indicate how the
@@ -64,14 +67,14 @@ class Module:
64
67
  injected each time.
65
68
  """
66
69
 
67
- def singleton(
70
+ def singleton[T](
68
71
  self,
69
- wrapped: Callable[..., Any] = ...,
72
+ wrapped: Callable[..., T] = ...,
70
73
  /,
71
74
  *,
72
75
  inject: bool = ...,
73
- on: type | Iterable[type] | UnionType = ...,
74
- mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
76
+ on: TypeInfo[T] = ...,
77
+ mode: InjectableMode | InjectableModeStr = ...,
75
78
  ):
76
79
  """
77
80
  Decorator applicable to a class or function. It is used to indicate how the
@@ -86,37 +89,37 @@ class Module:
86
89
  registered.
87
90
  """
88
91
 
89
- def set_constant(
92
+ def set_constant[T](
90
93
  self,
91
- instance: _T,
92
- on: type | Iterable[type] | UnionType = ...,
94
+ instance: T,
95
+ on: TypeInfo[T] = ...,
93
96
  *,
94
- mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
95
- ) -> _T:
97
+ mode: InjectableMode | InjectableModeStr = ...,
98
+ ) -> T:
96
99
  """
97
100
  Function for registering a specific instance to be injected. This is useful for
98
101
  registering global variables. The difference with the singleton decorator is
99
102
  that no dependencies are resolved, so the module doesn't need to be locked.
100
103
  """
101
104
 
102
- def resolve(self, cls: type[_T]) -> _T:
105
+ def resolve[T](self, cls: type[T]) -> T:
103
106
  """
104
107
  Function used to retrieve an instance associated with the type passed in
105
108
  parameter or an exception will be raised.
106
109
  """
107
110
 
108
- def get_instance(self, cls: type[_T]) -> _T | None:
111
+ def get_instance[T](self, cls: type[T]) -> T | None:
109
112
  """
110
113
  Function used to retrieve an instance associated with the type passed in
111
114
  parameter or return `None`.
112
115
  """
113
116
 
114
- def get_lazy_instance(
117
+ def get_lazy_instance[T](
115
118
  self,
116
- cls: type[_T],
119
+ cls: type[T],
117
120
  *,
118
121
  cache: bool = ...,
119
- ) -> Invertible[_T | None]:
122
+ ) -> Invertible[T | None]:
120
123
  """
121
124
  Function used to retrieve an instance associated with the type passed in
122
125
  parameter or `None`. Return a `Invertible` object. To access the instance
@@ -126,19 +129,24 @@ class Module:
126
129
  Example: instance = ~lazy_instance
127
130
  """
128
131
 
132
+ def init_modules(self, *modules: Module) -> Self:
133
+ """
134
+ Function to clean modules in use and to use those passed as parameters.
135
+ """
136
+
129
137
  def use(
130
138
  self,
131
139
  module: Module,
132
140
  *,
133
- priority: ModulePriority | Literal["low", "high"] = ...,
134
- ):
141
+ priority: ModulePriority | ModulePriorityStr = ...,
142
+ ) -> Self:
135
143
  """
136
144
  Function for using another module. Using another module replaces the module's
137
145
  dependencies with those of the module used. If the dependency is not found, it
138
146
  will be searched for in the module's dependency container.
139
147
  """
140
148
 
141
- def stop_using(self, module: Module):
149
+ def stop_using(self, module: Module) -> Self:
142
150
  """
143
151
  Function to remove a module in use.
144
152
  """
@@ -147,7 +155,7 @@ class Module:
147
155
  self,
148
156
  module: Module,
149
157
  *,
150
- priority: ModulePriority | Literal["low", "high"] = ...,
158
+ priority: ModulePriority | ModulePriorityStr = ...,
151
159
  ) -> ContextManager | ContextDecorator:
152
160
  """
153
161
  Context manager or decorator for temporary use of a module.
@@ -156,8 +164,8 @@ class Module:
156
164
  def change_priority(
157
165
  self,
158
166
  module: Module,
159
- priority: ModulePriority | Literal["low", "high"],
160
- ):
167
+ priority: ModulePriority | ModulePriorityStr,
168
+ ) -> Self:
161
169
  """
162
170
  Function for changing the priority of a module in use.
163
171
  There are two priority values:
@@ -166,27 +174,38 @@ class Module:
166
174
  * **HIGH**: The module concerned becomes the most important of the modules used.
167
175
  """
168
176
 
169
- def unlock(self):
177
+ def unlock(self) -> Self:
170
178
  """
171
179
  Function to unlock the module by deleting cached instances of singletons.
172
180
  """
173
181
 
182
+ @classmethod
183
+ def from_name(cls, name: str) -> Self:
184
+ """
185
+ Class method for getting or creating a module by name.
186
+ """
187
+
188
+ @classmethod
189
+ def default(cls) -> Self:
190
+ """
191
+ Class method for getting the default module.
192
+ """
193
+
174
194
  @final
175
- class ModulePriority(str, Enum):
195
+ class ModulePriority(StrEnum):
176
196
  LOW = ...
177
197
  HIGH = ...
178
198
 
179
199
  @runtime_checkable
180
- class Injectable(Protocol[_T_co]):
181
- def __init__(self, factory: Callable[[], _T_co] = ..., /): ...
200
+ class Injectable[T](Protocol):
182
201
  @property
183
202
  def is_locked(self) -> bool: ...
184
203
  def unlock(self): ...
185
204
  @abstractmethod
186
- def get_instance(self) -> _T_co: ...
205
+ def get_instance(self) -> T: ...
187
206
 
188
207
  @final
189
- class InjectableMode(str, Enum):
208
+ class InjectableMode(StrEnum):
190
209
  FALLBACK = ...
191
210
  NORMAL = ...
192
211
  OVERRIDE = ...
injection/common/event.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from contextlib import ExitStack, contextmanager, suppress
3
3
  from dataclasses import dataclass, field
4
- from typing import ContextManager
4
+ from typing import ContextManager, Self
5
5
  from weakref import WeakSet
6
6
 
7
7
  __all__ = ("Event", "EventChannel", "EventListener")
@@ -36,11 +36,11 @@ class EventChannel:
36
36
 
37
37
  yield
38
38
 
39
- def add_listener(self, listener: EventListener):
39
+ def add_listener(self, listener: EventListener) -> Self:
40
40
  self.__listeners.add(listener)
41
41
  return self
42
42
 
43
- def remove_listener(self, listener: EventListener):
43
+ def remove_listener(self, listener: EventListener) -> Self:
44
44
  with suppress(KeyError):
45
45
  self.__listeners.remove(listener)
46
46
 
@@ -1,23 +1,21 @@
1
1
  from abc import abstractmethod
2
2
  from collections.abc import Callable
3
3
  from dataclasses import dataclass
4
- from typing import Protocol, TypeVar, runtime_checkable
4
+ from typing import Protocol, runtime_checkable
5
5
 
6
6
  __all__ = ("Invertible", "SimpleInvertible")
7
7
 
8
- _T_co = TypeVar("_T_co", covariant=True)
9
-
10
8
 
11
9
  @runtime_checkable
12
- class Invertible(Protocol[_T_co]):
10
+ class Invertible[T](Protocol):
13
11
  @abstractmethod
14
- def __invert__(self) -> _T_co:
12
+ def __invert__(self) -> T:
15
13
  raise NotImplementedError
16
14
 
17
15
 
18
16
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
19
- class SimpleInvertible(Invertible[_T_co]):
20
- callable: Callable[[], _T_co]
17
+ class SimpleInvertible[T](Invertible[T]):
18
+ callable: Callable[[], T]
21
19
 
22
- def __invert__(self) -> _T_co:
20
+ def __invert__(self) -> T:
23
21
  return self.callable()
injection/common/lazy.py CHANGED
@@ -1,31 +1,26 @@
1
1
  from collections.abc import Callable, Iterator, Mapping
2
2
  from types import MappingProxyType
3
- from typing import TypeVar
4
3
 
5
4
  from injection.common.invertible import Invertible
6
5
 
7
6
  __all__ = ("Lazy", "LazyMapping")
8
7
 
9
- _T = TypeVar("_T")
10
- _K = TypeVar("_K")
11
- _V = TypeVar("_V")
12
8
 
13
-
14
- class Lazy(Invertible[_T]):
9
+ class Lazy[T](Invertible[T]):
15
10
  __slots__ = ("__cache", "__is_set")
16
11
 
17
- def __init__(self, factory: Callable[[], _T]):
12
+ def __init__(self, factory: Callable[[], T]):
18
13
  self.__setup_cache(factory)
19
14
 
20
- def __invert__(self) -> _T:
15
+ def __invert__(self) -> T:
21
16
  return next(self.__cache)
22
17
 
23
18
  @property
24
19
  def is_set(self) -> bool:
25
20
  return self.__is_set
26
21
 
27
- def __setup_cache(self, factory: Callable[[], _T]):
28
- def cache_generator() -> Iterator[_T]:
22
+ def __setup_cache(self, factory: Callable[[], T]):
23
+ def cache_generator() -> Iterator[T]:
29
24
  nonlocal factory
30
25
  cached = factory()
31
26
  self.__is_set = True
@@ -38,16 +33,16 @@ class Lazy(Invertible[_T]):
38
33
  self.__is_set = False
39
34
 
40
35
 
41
- class LazyMapping(Mapping[_K, _V]):
36
+ class LazyMapping[K, V](Mapping[K, V]):
42
37
  __slots__ = ("__lazy",)
43
38
 
44
- def __init__(self, iterator: Iterator[tuple[_K, _V]]):
39
+ def __init__(self, iterator: Iterator[tuple[K, V]]):
45
40
  self.__lazy = Lazy(lambda: MappingProxyType(dict(iterator)))
46
41
 
47
- def __getitem__(self, key: _K, /) -> _V:
42
+ def __getitem__(self, key: K, /) -> V:
48
43
  return (~self.__lazy)[key]
49
44
 
50
- def __iter__(self) -> Iterator[_K]:
45
+ def __iter__(self) -> Iterator[K]:
51
46
  yield from ~self.__lazy
52
47
 
53
48
  def __len__(self) -> int:
@@ -3,10 +3,10 @@ from threading import RLock
3
3
 
4
4
  __all__ = ("synchronized",)
5
5
 
6
- __lock = RLock()
7
-
8
6
 
9
7
  @contextmanager
10
8
  def synchronized():
11
- with __lock:
12
- yield
9
+ lock = RLock()
10
+
11
+ with lock:
12
+ yield lock
@@ -1,48 +1,75 @@
1
- from collections.abc import Iterable, Iterator
1
+ from collections.abc import Callable, Iterable, Iterator
2
2
  from inspect import get_annotations, isfunction
3
- from types import NoneType, UnionType
4
- from typing import Annotated, Any, Union, get_args, get_origin
3
+ from types import UnionType
4
+ from typing import (
5
+ Annotated,
6
+ Any,
7
+ NamedTuple,
8
+ Self,
9
+ Union,
10
+ get_args,
11
+ get_origin,
12
+ )
5
13
 
6
- __all__ = ("find_types", "format_type", "get_origins")
14
+ __all__ = ("TypeInfo", "TypeReport", "analyze_types", "get_return_types")
7
15
 
16
+ type TypeInfo[T] = type[T] | Callable[..., T] | Iterable[TypeInfo[T]] | UnionType
8
17
 
9
- def format_type(cls: type | Any) -> str:
10
- try:
11
- return f"{cls.__module__}.{cls.__qualname__}"
12
- except AttributeError:
13
- return str(cls)
14
18
 
19
+ class TypeReport[T](NamedTuple):
20
+ origin: type[T]
21
+ args: tuple[Any, ...]
15
22
 
16
- def get_origins(*types: type | Any) -> Iterator[type | Any]:
17
- for tp in types:
18
- origin = get_origin(tp) or tp
23
+ @property
24
+ def type(self) -> type[T]:
25
+ origin = self.origin
26
+
27
+ if args := self.args:
28
+ return origin[*args]
29
+
30
+ return origin
31
+
32
+ @property
33
+ def no_args(self) -> Self:
34
+ if self.args:
35
+ return type(self)(self.origin, ())
19
36
 
20
- if origin in (None, NoneType):
37
+ return self
38
+
39
+
40
+ def analyze_types(*types: type | Any) -> Iterator[TypeReport[Any]]:
41
+ for tp in types:
42
+ if tp is None:
21
43
  continue
22
44
 
23
- elif origin in (Union, UnionType):
24
- args = get_args(tp)
45
+ origin = get_origin(tp)
46
+
47
+ if origin is Union or isinstance(tp, UnionType):
48
+ inner_types = get_args(tp)
25
49
 
26
- elif origin is Annotated is not tp:
27
- args = get_args(tp)[:1]
50
+ elif origin is Annotated:
51
+ inner_types = get_args(tp)[:1]
28
52
 
29
53
  else:
30
- yield origin
54
+ yield TypeReport(origin or tp, get_args(tp))
31
55
  continue
32
56
 
33
- yield from get_origins(*args)
57
+ yield from analyze_types(*inner_types)
34
58
 
35
59
 
36
- def find_types(*args: Any) -> Iterator[type | UnionType]:
37
- for argument in args:
38
- if isinstance(argument, Iterable) and not isinstance(argument, type | str):
39
- arguments = argument
60
+ def get_return_types(*args: TypeInfo[Any]) -> Iterator[type | UnionType]:
61
+ for arg in args:
62
+ if isinstance(arg, Iterable) and not isinstance(
63
+ get_origin(arg) or arg,
64
+ type | str,
65
+ ):
66
+ inner_args = arg
40
67
 
41
- elif isfunction(argument):
42
- arguments = (get_annotations(argument, eval_str=True).get("return"),)
68
+ elif isfunction(arg):
69
+ inner_args = (get_annotations(arg, eval_str=True).get("return"),)
43
70
 
44
71
  else:
45
- yield argument
72
+ yield arg
46
73
  continue
47
74
 
48
- yield from find_types(*arguments)
75
+ yield from get_return_types(*inner_args)
injection/core/module.py CHANGED
@@ -14,7 +14,7 @@ from collections.abc import (
14
14
  )
15
15
  from contextlib import contextmanager, suppress
16
16
  from dataclasses import dataclass, field
17
- from enum import Enum
17
+ from enum import StrEnum
18
18
  from functools import partialmethod, singledispatchmethod, update_wrapper
19
19
  from inspect import Signature, isclass
20
20
  from queue import Queue
@@ -27,7 +27,7 @@ from typing import (
27
27
  NamedTuple,
28
28
  NoReturn,
29
29
  Protocol,
30
- TypeVar,
30
+ Self,
31
31
  runtime_checkable,
32
32
  )
33
33
 
@@ -35,7 +35,12 @@ from injection.common.event import Event, EventChannel, EventListener
35
35
  from injection.common.invertible import Invertible, SimpleInvertible
36
36
  from injection.common.lazy import Lazy, LazyMapping
37
37
  from injection.common.tools.threading import synchronized
38
- from injection.common.tools.type import find_types, format_type, get_origins
38
+ from injection.common.tools.type import (
39
+ TypeInfo,
40
+ TypeReport,
41
+ analyze_types,
42
+ get_return_types,
43
+ )
39
44
  from injection.exceptions import (
40
45
  InjectionError,
41
46
  ModuleError,
@@ -44,13 +49,18 @@ from injection.exceptions import (
44
49
  NoInjectable,
45
50
  )
46
51
 
47
- __all__ = ("Injectable", "Mode", "Module", "Priority")
52
+ __all__ = (
53
+ "Injectable",
54
+ "InjectableFactory",
55
+ "Mode",
56
+ "ModeStr",
57
+ "Module",
58
+ "Priority",
59
+ "PriorityStr",
60
+ )
48
61
 
49
62
  _logger = logging.getLogger(__name__)
50
63
 
51
- _T = TypeVar("_T")
52
- _T_co = TypeVar("_T_co", covariant=True)
53
-
54
64
  """
55
65
  Events
56
66
  """
@@ -63,15 +73,15 @@ class ContainerEvent(Event, ABC):
63
73
 
64
74
  @dataclass(frozen=True, slots=True)
65
75
  class ContainerDependenciesUpdated(ContainerEvent):
66
- classes: Collection[type]
76
+ reports: Collection[TypeReport]
67
77
  mode: Mode
68
78
 
69
79
  def __str__(self) -> str:
70
- length = len(self.classes)
71
- formatted_classes = ", ".join(f"`{format_type(cls)}`" for cls in self.classes)
80
+ length = len(self.reports)
81
+ formatted_types = ", ".join(f"`{report.type}`" for report in self.reports)
72
82
  return (
73
- f"{length} container dependenc{'ies' if length > 1 else 'y'} have been "
74
- f"updated{f': {formatted_classes}' if formatted_classes else ''}."
83
+ f"{length} container dependenc{'ies' if length > 1 else 'y'} have "
84
+ f"been updated{f': {formatted_types}' if formatted_types else ''}."
75
85
  )
76
86
 
77
87
 
@@ -134,12 +144,9 @@ Injectables
134
144
 
135
145
 
136
146
  @runtime_checkable
137
- class Injectable(Protocol[_T_co]):
147
+ class Injectable[T](Protocol):
138
148
  __slots__ = ()
139
149
 
140
- def __init__(self, __factory: Callable[[], _T_co] = None, /):
141
- pass
142
-
143
150
  @property
144
151
  def is_locked(self) -> bool:
145
152
  return False
@@ -148,26 +155,26 @@ class Injectable(Protocol[_T_co]):
148
155
  return
149
156
 
150
157
  @abstractmethod
151
- def get_instance(self) -> _T_co:
158
+ def get_instance(self) -> T:
152
159
  raise NotImplementedError
153
160
 
154
161
 
155
162
  @dataclass(repr=False, frozen=True, slots=True)
156
- class BaseInjectable(Injectable[_T], ABC):
157
- factory: Callable[[], _T]
163
+ class BaseInjectable[T](Injectable[T], ABC):
164
+ factory: Callable[[], T]
158
165
 
159
166
 
160
- class NewInjectable(BaseInjectable[_T]):
167
+ class NewInjectable[T](BaseInjectable[T]):
161
168
  __slots__ = ()
162
169
 
163
- def get_instance(self) -> _T:
170
+ def get_instance(self) -> T:
164
171
  return self.factory()
165
172
 
166
173
 
167
- class SingletonInjectable(BaseInjectable[_T]):
174
+ class SingletonInjectable[T](BaseInjectable[T]):
168
175
  __slots__ = ("__dict__",)
169
176
 
170
- __INSTANCE_KEY: ClassVar[str] = "$instance"
177
+ __key: ClassVar[str] = "$instance"
171
178
 
172
179
  @property
173
180
  def cache(self) -> MutableMapping[str, Any]:
@@ -175,28 +182,28 @@ class SingletonInjectable(BaseInjectable[_T]):
175
182
 
176
183
  @property
177
184
  def is_locked(self) -> bool:
178
- return self.__INSTANCE_KEY in self.cache
185
+ return self.__key in self.cache
179
186
 
180
187
  def unlock(self):
181
188
  self.cache.clear()
182
189
 
183
- def get_instance(self) -> _T:
190
+ def get_instance(self) -> T:
184
191
  with suppress(KeyError):
185
- return self.cache[self.__INSTANCE_KEY]
192
+ return self.cache[self.__key]
186
193
 
187
194
  with synchronized():
188
195
  instance = self.factory()
189
- self.cache[self.__INSTANCE_KEY] = instance
196
+ self.cache[self.__key] = instance
190
197
 
191
198
  return instance
192
199
 
193
200
 
194
201
  @dataclass(repr=False, frozen=True, slots=True)
195
- class ShouldBeInjectable(Injectable[_T]):
196
- cls: type[_T]
202
+ class ShouldBeInjectable[T](Injectable[T]):
203
+ cls: type[T]
197
204
 
198
205
  def get_instance(self) -> NoReturn:
199
- raise InjectionError(f"`{format_type(self.cls)}` should be an injectable.")
206
+ raise InjectionError(f"`{self.cls}` should be an injectable.")
200
207
 
201
208
 
202
209
  """
@@ -209,7 +216,7 @@ class Broker(Protocol):
209
216
  __slots__ = ()
210
217
 
211
218
  @abstractmethod
212
- def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
219
+ def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
213
220
  raise NotImplementedError
214
221
 
215
222
  @abstractmethod
@@ -222,7 +229,7 @@ class Broker(Protocol):
222
229
  raise NotImplementedError
223
230
 
224
231
  @abstractmethod
225
- def unlock(self):
232
+ def unlock(self) -> Self:
226
233
  raise NotImplementedError
227
234
 
228
235
 
@@ -231,7 +238,7 @@ Container
231
238
  """
232
239
 
233
240
 
234
- class Mode(str, Enum):
241
+ class Mode(StrEnum):
235
242
  FALLBACK = "fallback"
236
243
  NORMAL = "normal"
237
244
  OVERRIDE = "override"
@@ -241,36 +248,37 @@ class Mode(str, Enum):
241
248
  return tuple(type(self)).index(self)
242
249
 
243
250
  @classmethod
244
- def get_default(cls):
251
+ def get_default(cls) -> Mode:
245
252
  return cls.NORMAL
246
253
 
247
254
 
248
- ModeStr = Literal["fallback", "normal", "override"]
255
+ type ModeStr = Literal["fallback", "normal", "override"]
249
256
 
250
257
 
251
- class Record(NamedTuple):
252
- injectable: Injectable
258
+ class Record[T](NamedTuple):
259
+ injectable: Injectable[T]
253
260
  mode: Mode
254
261
 
255
262
 
256
263
  @dataclass(repr=False, frozen=True, slots=True)
257
264
  class Container(Broker):
258
- __records: dict[type, Record] = field(default_factory=dict, init=False)
265
+ __records: dict[TypeReport, Record] = field(default_factory=dict, init=False)
259
266
  __channel: EventChannel = field(default_factory=EventChannel, init=False)
260
267
 
261
- def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
262
- for cls in get_origins(cls):
263
- try:
264
- injectable, _ = self.__records[cls]
265
- except KeyError:
266
- continue
268
+ def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
269
+ for report in analyze_types(cls):
270
+ for scoped_report in dict.fromkeys((report, report.no_args)):
271
+ try:
272
+ injectable, _ = self.__records[scoped_report]
273
+ except KeyError:
274
+ continue
267
275
 
268
- return injectable
276
+ return injectable
269
277
 
270
278
  raise NoInjectable(cls)
271
279
 
272
280
  def __contains__(self, cls: type | UnionType, /) -> bool:
273
- return any(cls in self.__records for cls in get_origins(cls))
281
+ return any(report in self.__records for report in analyze_types(cls))
274
282
 
275
283
  @property
276
284
  def is_locked(self) -> bool:
@@ -281,16 +289,16 @@ class Container(Broker):
281
289
  return frozenset(injectable for injectable, _ in self.__records.values())
282
290
 
283
291
  @synchronized()
284
- def update(
292
+ def update[T](
285
293
  self,
286
- classes: Iterable[type | UnionType],
287
- injectable: Injectable,
294
+ classes: Iterable[type[T] | UnionType],
295
+ injectable: Injectable[T],
288
296
  mode: Mode | ModeStr,
289
- ):
297
+ ) -> Self:
290
298
  mode = Mode(mode)
291
299
  records = {
292
- cls: Record(injectable, mode)
293
- for cls in self.__classes_to_update(classes, mode)
300
+ report: Record(injectable, mode)
301
+ for report in self.__prepare_reports_for_updating(classes, mode)
294
302
  }
295
303
 
296
304
  if records:
@@ -302,43 +310,43 @@ class Container(Broker):
302
310
  return self
303
311
 
304
312
  @synchronized()
305
- def unlock(self):
313
+ def unlock(self) -> Self:
306
314
  for injectable in self.__injectables:
307
315
  injectable.unlock()
308
316
 
309
317
  return self
310
318
 
311
- def add_listener(self, listener: EventListener):
319
+ def add_listener(self, listener: EventListener) -> Self:
312
320
  self.__channel.add_listener(listener)
313
321
  return self
314
322
 
315
- def notify(self, event: Event):
323
+ def notify(self, event: Event) -> ContextManager:
316
324
  return self.__channel.dispatch(event)
317
325
 
318
- def __classes_to_update(
326
+ def __prepare_reports_for_updating(
319
327
  self,
320
328
  classes: Iterable[type | UnionType],
321
329
  mode: Mode,
322
- ) -> Iterator[type]:
330
+ ) -> Iterator[TypeReport]:
323
331
  rank = mode.rank
324
332
 
325
- for cls in frozenset(get_origins(*classes)):
333
+ for report in frozenset(analyze_types(*classes)):
326
334
  try:
327
- _, current_mode = self.__records[cls]
335
+ _, current_mode = self.__records[report]
328
336
 
329
337
  except KeyError:
330
338
  pass
331
339
 
332
340
  else:
333
- if mode == current_mode:
341
+ if mode == current_mode and mode != Mode.OVERRIDE:
334
342
  raise RuntimeError(
335
- f"An injectable already exists for the class `{format_type(cls)}`."
343
+ f"An injectable already exists for the class `{report.type}`."
336
344
  )
337
345
 
338
346
  elif rank < current_mode.rank:
339
347
  continue
340
348
 
341
- yield cls
349
+ yield report
342
350
 
343
351
 
344
352
  """
@@ -346,47 +354,57 @@ Module
346
354
  """
347
355
 
348
356
 
349
- class Priority(str, Enum):
357
+ class Priority(StrEnum):
350
358
  LOW = "low"
351
359
  HIGH = "high"
352
360
 
353
361
  @classmethod
354
- def get_default(cls):
362
+ def get_default(cls) -> Priority:
355
363
  return cls.LOW
356
364
 
357
365
 
358
- PriorityStr = Literal["low", "high"]
366
+ type PriorityStr = Literal["low", "high"]
359
367
 
368
+ type InjectableFactory[T] = Callable[[Callable[..., T]], Injectable[T]]
360
369
 
361
- @dataclass(repr=False, eq=False, frozen=True, slots=True)
370
+
371
+ @dataclass(eq=False, frozen=True, slots=True)
362
372
  class Module(EventListener, Broker):
363
373
  name: str | None = field(default=None)
364
- __channel: EventChannel = field(default_factory=EventChannel, init=False)
365
- __container: Container = field(default_factory=Container, init=False)
374
+ __channel: EventChannel = field(
375
+ default_factory=EventChannel,
376
+ init=False,
377
+ repr=False,
378
+ )
379
+ __container: Container = field(
380
+ default_factory=Container,
381
+ init=False,
382
+ repr=False,
383
+ )
366
384
  __modules: OrderedDict[Module, None] = field(
367
385
  default_factory=OrderedDict,
368
386
  init=False,
387
+ repr=False,
369
388
  )
370
389
 
390
+ __instances: ClassVar[dict[str, Module]] = {}
391
+
371
392
  def __post_init__(self):
372
393
  self.__container.add_listener(self)
373
394
 
374
- def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
395
+ def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
375
396
  for broker in self.__brokers:
376
397
  with suppress(KeyError):
377
398
  return broker[cls]
378
399
 
379
400
  raise NoInjectable(cls)
380
401
 
381
- def __setitem__(self, cls: type | UnionType, injectable: Injectable, /):
402
+ def __setitem__[T](self, cls: type[T] | UnionType, injectable: Injectable[T], /):
382
403
  self.update((cls,), injectable)
383
404
 
384
405
  def __contains__(self, cls: type | UnionType, /) -> bool:
385
406
  return any(cls in broker for broker in self.__brokers)
386
407
 
387
- def __str__(self) -> str:
388
- return self.name or object.__str__(self)
389
-
390
408
  @property
391
409
  def is_locked(self) -> bool:
392
410
  return any(broker.is_locked for broker in self.__brokers)
@@ -396,20 +414,20 @@ class Module(EventListener, Broker):
396
414
  yield from tuple(self.__modules)
397
415
  yield self.__container
398
416
 
399
- def injectable(
417
+ def injectable[T](
400
418
  self,
401
- wrapped: Callable[..., Any] = None,
419
+ wrapped: Callable[..., T] = None,
402
420
  /,
403
421
  *,
404
- cls: type[Injectable] = NewInjectable,
422
+ cls: InjectableFactory[T] = NewInjectable,
405
423
  inject: bool = True,
406
- on: type | Iterable[type] | UnionType = (),
424
+ on: TypeInfo[T] = (),
407
425
  mode: Mode | ModeStr = Mode.get_default(),
408
426
  ):
409
427
  def decorator(wp):
410
428
  factory = self.inject(wp, return_factory=True) if inject else wp
411
429
  injectable = cls(factory)
412
- classes = find_types(wp, on)
430
+ classes = get_return_types(wp, on)
413
431
  self.update(classes, injectable, mode)
414
432
  return wp
415
433
 
@@ -428,18 +446,18 @@ class Module(EventListener, Broker):
428
446
 
429
447
  return decorator(wrapped) if wrapped else decorator
430
448
 
431
- def set_constant(
449
+ def set_constant[T](
432
450
  self,
433
- instance: _T,
434
- on: type | Iterable[type] | UnionType = (),
451
+ instance: T,
452
+ on: TypeInfo[T] = (),
435
453
  *,
436
454
  mode: Mode | ModeStr = Mode.get_default(),
437
- ) -> _T:
455
+ ) -> T:
438
456
  cls = type(instance)
439
457
  self.injectable(
440
458
  lambda: instance,
441
459
  inject=False,
442
- on=(cls, on), # type: ignore
460
+ on=(cls, on),
443
461
  mode=mode,
444
462
  )
445
463
  return instance
@@ -458,7 +476,7 @@ class Module(EventListener, Broker):
458
476
 
459
477
  function = InjectedFunction(wp)
460
478
 
461
- @function.on_setup
479
+ @function.on_setup(block=False)
462
480
  def listen():
463
481
  function.update(self)
464
482
  self.add_listener(function)
@@ -467,22 +485,22 @@ class Module(EventListener, Broker):
467
485
 
468
486
  return decorator(wrapped) if wrapped else decorator
469
487
 
470
- def resolve(self, cls: type[_T]) -> _T:
488
+ def resolve[T](self, cls: type[T]) -> T:
471
489
  injectable = self[cls]
472
490
  return injectable.get_instance()
473
491
 
474
- def get_instance(self, cls: type[_T]) -> _T | None:
492
+ def get_instance[T](self, cls: type[T]) -> T | None:
475
493
  try:
476
494
  return self.resolve(cls)
477
495
  except KeyError:
478
496
  return None
479
497
 
480
- def get_lazy_instance(
498
+ def get_lazy_instance[T](
481
499
  self,
482
- cls: type[_T],
500
+ cls: type[T],
483
501
  *,
484
502
  cache: bool = False,
485
- ) -> Invertible[_T | None]:
503
+ ) -> Invertible[T | None]:
486
504
  if cache:
487
505
  return Lazy(lambda: self.get_instance(cls))
488
506
 
@@ -490,21 +508,30 @@ class Module(EventListener, Broker):
490
508
  function.set_owner(cls)
491
509
  return SimpleInvertible(function)
492
510
 
493
- def update(
511
+ def update[T](
494
512
  self,
495
- classes: Iterable[type | UnionType],
496
- injectable: Injectable,
513
+ classes: Iterable[type[T] | UnionType],
514
+ injectable: Injectable[T],
497
515
  mode: Mode | ModeStr = Mode.get_default(),
498
- ):
516
+ ) -> Self:
499
517
  self.__container.update(classes, injectable, mode)
500
518
  return self
501
519
 
520
+ def init_modules(self, *modules: Module) -> Self:
521
+ for module in tuple(self.__modules):
522
+ self.stop_using(module)
523
+
524
+ for module in modules:
525
+ self.use(module)
526
+
527
+ return self
528
+
502
529
  def use(
503
530
  self,
504
531
  module: Module,
505
532
  *,
506
533
  priority: Priority | PriorityStr = Priority.get_default(),
507
- ):
534
+ ) -> Self:
508
535
  if module is self:
509
536
  raise ModuleError("Module can't be used by itself.")
510
537
 
@@ -521,7 +548,7 @@ class Module(EventListener, Broker):
521
548
 
522
549
  return self
523
550
 
524
- def stop_using(self, module: Module):
551
+ def stop_using(self, module: Module) -> Self:
525
552
  event = ModuleRemoved(self, module)
526
553
 
527
554
  with suppress(KeyError):
@@ -542,7 +569,7 @@ class Module(EventListener, Broker):
542
569
  yield
543
570
  self.stop_using(module)
544
571
 
545
- def change_priority(self, module: Module, priority: Priority | PriorityStr):
572
+ def change_priority(self, module: Module, priority: Priority | PriorityStr) -> Self:
546
573
  priority = Priority(priority)
547
574
  event = ModulePriorityUpdated(self, module, priority)
548
575
 
@@ -552,17 +579,17 @@ class Module(EventListener, Broker):
552
579
  return self
553
580
 
554
581
  @synchronized()
555
- def unlock(self):
582
+ def unlock(self) -> Self:
556
583
  for broker in self.__brokers:
557
584
  broker.unlock()
558
585
 
559
586
  return self
560
587
 
561
- def add_listener(self, listener: EventListener):
588
+ def add_listener(self, listener: EventListener) -> Self:
562
589
  self.__channel.add_listener(listener)
563
590
  return self
564
591
 
565
- def remove_listener(self, listener: EventListener):
592
+ def remove_listener(self, listener: EventListener) -> Self:
566
593
  self.__channel.remove_listener(listener)
567
594
  return self
568
595
 
@@ -592,6 +619,19 @@ class Module(EventListener, Broker):
592
619
  f"`{module}` can't be found in the modules used by `{self}`."
593
620
  ) from exc
594
621
 
622
+ @classmethod
623
+ def from_name(cls, name: str) -> Self:
624
+ with suppress(KeyError):
625
+ return cls.__instances[name]
626
+
627
+ instance = cls(name)
628
+ cls.__instances[name] = instance
629
+ return instance
630
+
631
+ @classmethod
632
+ def default(cls) -> Self:
633
+ return cls.from_name("default")
634
+
595
635
 
596
636
  """
597
637
  InjectedFunction
@@ -621,15 +661,15 @@ class Dependencies:
621
661
  return OrderedDict(self)
622
662
 
623
663
  @classmethod
624
- def from_mapping(cls, mapping: Mapping[str, Injectable]):
625
- return cls(mapping=mapping)
664
+ def from_mapping(cls, mapping: Mapping[str, Injectable]) -> Self:
665
+ return cls(mapping)
626
666
 
627
667
  @classmethod
628
- def empty(cls):
668
+ def empty(cls) -> Self:
629
669
  return cls.from_mapping({})
630
670
 
631
671
  @classmethod
632
- def resolve(cls, signature: Signature, module: Module, owner: type = None):
672
+ def resolve(cls, signature: Signature, module: Module, owner: type = None) -> Self:
633
673
  dependencies = LazyMapping(cls.__resolver(signature, module, owner))
634
674
  return cls.from_mapping(dependencies)
635
675
 
@@ -705,7 +745,7 @@ class InjectedFunction(EventListener):
705
745
  arguments = self.bind(args, kwargs)
706
746
  return self.wrapped(*arguments.args, **arguments.kwargs)
707
747
 
708
- def __get__(self, instance: object = None, owner: type = None):
748
+ def __get__(self, instance: object = None, owner: type = None) -> Self | MethodType:
709
749
  if instance is None:
710
750
  return self
711
751
 
@@ -739,7 +779,7 @@ class InjectedFunction(EventListener):
739
779
  )
740
780
  return Arguments(bound.args, bound.kwargs)
741
781
 
742
- def set_owner(self, owner: type):
782
+ def set_owner(self, owner: type) -> Self:
743
783
  if self.__dependencies.are_resolved:
744
784
  raise TypeError(
745
785
  "Function owner must be assigned before dependencies are resolved."
@@ -752,19 +792,19 @@ class InjectedFunction(EventListener):
752
792
  return self
753
793
 
754
794
  @synchronized()
755
- def update(self, module: Module):
795
+ def update(self, module: Module) -> Self:
756
796
  self.__dependencies = Dependencies.resolve(self.signature, module, self.__owner)
757
797
  return self
758
798
 
759
- def on_setup(self, wrapped: Callable[[], Any] = None, /):
799
+ def on_setup(self, wrapped: Callable[[], Any] = None, /, *, block: bool = True):
760
800
  def decorator(wp):
761
- self.__setup_queue.put(wp)
801
+ self.__setup_queue.put(wp, block=block)
762
802
  return wp
763
803
 
764
804
  return decorator(wrapped) if wrapped else decorator
765
805
 
766
806
  @singledispatchmethod
767
- def on_event(self, event: Event, /) -> ContextManager | None: # type: ignore
807
+ def on_event(self, event: Event, /) -> None: # type: ignore
768
808
  return None
769
809
 
770
810
  @on_event.register
@@ -773,7 +813,7 @@ class InjectedFunction(EventListener):
773
813
  yield
774
814
  self.update(event.on_module)
775
815
 
776
- def __set_signature(self):
816
+ def __set_signature(self) -> Self:
777
817
  self.__signature__ = inspect.signature(self.wrapped, eval_str=True)
778
818
  return self
779
819
 
injection/exceptions.py CHANGED
@@ -1,7 +1,5 @@
1
1
  from typing import Any
2
2
 
3
- from injection.common.tools.type import format_type
4
-
5
3
  __all__ = (
6
4
  "InjectionError",
7
5
  "NoInjectable",
@@ -15,15 +13,15 @@ class InjectionError(Exception):
15
13
  pass
16
14
 
17
15
 
18
- class NoInjectable(KeyError, InjectionError):
16
+ class NoInjectable[T](KeyError, InjectionError):
19
17
  __slots__ = ("__class",)
20
18
 
21
- def __init__(self, cls: type | Any):
22
- super().__init__(f"No injectable for `{format_type(cls)}`.")
19
+ def __init__(self, cls: type[T] | Any):
20
+ super().__init__(f"No injectable for `{cls}`.")
23
21
  self.__class = cls
24
22
 
25
23
  @property
26
- def cls(self) -> type:
24
+ def cls(self) -> type[T]:
27
25
  return self.__class
28
26
 
29
27
 
@@ -1,13 +1,11 @@
1
- from typing import Any, TypeVar
1
+ from typing import Any
2
2
 
3
3
  from rodi import ContainerProtocol
4
4
 
5
- from injection import Module, default_module
5
+ from injection import Module
6
6
 
7
7
  __all__ = ("InjectionServices",)
8
8
 
9
- _T = TypeVar("_T")
10
-
11
9
 
12
10
  class InjectionServices(ContainerProtocol):
13
11
  """
@@ -16,8 +14,8 @@ class InjectionServices(ContainerProtocol):
16
14
 
17
15
  __slots__ = ("__module",)
18
16
 
19
- def __init__(self, module: Module = default_module):
20
- self.__module = module
17
+ def __init__(self, module: Module = None):
18
+ self.__module = module or Module.default()
21
19
 
22
20
  def __contains__(self, item: Any) -> bool:
23
21
  return item in self.__module
@@ -26,5 +24,5 @@ class InjectionServices(ContainerProtocol):
26
24
  self.__module.injectable(obj_type)
27
25
  return self
28
26
 
29
- def resolve(self, obj_type: type[_T] | Any, *args, **kwargs) -> _T:
27
+ def resolve[T](self, obj_type: type[T] | Any, *args, **kwargs) -> T:
30
28
  return self.__module.resolve(obj_type)
@@ -0,0 +1,38 @@
1
+ from contextlib import contextmanager
2
+
3
+ from injection import Module, ModulePriority
4
+
5
+ __all__ = (
6
+ "set_test_constant",
7
+ "should_be_test_injectable",
8
+ "test_injectable",
9
+ "test_singleton",
10
+ "use_test_injectables",
11
+ )
12
+
13
+
14
+ def get_test_module() -> Module:
15
+ return Module.from_name("testing")
16
+
17
+
18
+ _module = get_test_module()
19
+
20
+ set_test_constant = _module.set_constant
21
+ should_be_test_injectable = _module.should_be_injectable
22
+ test_injectable = _module.injectable
23
+ test_singleton = _module.singleton
24
+
25
+ del _module
26
+
27
+
28
+ @contextmanager
29
+ def use_test_injectables(*, on: Module = None, test_module: Module = None):
30
+ on = on or Module.default()
31
+ test_module = test_module or get_test_module()
32
+
33
+ for module in (on, test_module):
34
+ module.unlock()
35
+
36
+ with on.use_temporarily(test_module, priority=ModulePriority.HIGH):
37
+ yield
38
+ on.unlock()
@@ -0,0 +1,22 @@
1
+ from contextlib import ContextDecorator
2
+ from typing import ContextManager
3
+
4
+ from injection import Module
5
+
6
+ _module: Module = ...
7
+
8
+ set_test_constant = _module.set_constant
9
+ should_be_test_injectable = _module.should_be_injectable
10
+ test_injectable = _module.injectable
11
+ test_singleton = _module.singleton
12
+
13
+ del _module
14
+
15
+ def use_test_injectables(
16
+ *,
17
+ on: Module = ...,
18
+ test_module: Module = ...,
19
+ ) -> ContextManager | ContextDecorator:
20
+ """
21
+ Context manager or decorator for temporary use test module.
22
+ """
@@ -1,23 +1,21 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-injection
3
- Version: 0.8.5
3
+ Version: 0.9.1
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
7
7
  Keywords: dependencies,inject,injection
8
8
  Author: remimd
9
- Requires-Python: >=3.10,<4
9
+ Requires-Python: >=3.12,<4
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
12
  Classifier: Programming Language :: Python :: 3.12
15
13
  Project-URL: Repository, https://github.com/100nm/python-injection
16
14
  Description-Content-Type: text/markdown
17
15
 
18
16
  # Basic usage
19
17
 
20
- ## Create an injectable
18
+ ## Register an injectable
21
19
 
22
20
  > **Note**: If the class needs dependencies, these will be resolved when the instance is retrieved.
23
21
 
@@ -0,0 +1,21 @@
1
+ injection/__init__.py,sha256=LhfwYFMBw6tJ7XA_C353w61OPt4IuQQgs3zIjrwMIz8,654
2
+ injection/__init__.pyi,sha256=dfIQAR8L8Yr7dM-DODR4czwUd2a7zzFQHzb8mr1Q6P0,6235
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=noNcmJ96IQi0XJms0dyfrx_AvKZnQM0sZyxhc2l6qo0,527
6
+ injection/common/lazy.py,sha256=FEas6ewwOGWvRR8cflmyVvSLZd_-Fxd0QeIdvAM5I9c,1313
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=ThM3Z1_gHmsdT4Jp7PlZgJY0lsufc4InPO65485Ugsg,1739
10
+ injection/core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
11
+ injection/core/module.py,sha256=3FqU4XQgTNLI-VwpX1bKcRsLOaPeKSQ0sQuVsL_27I4,21625
12
+ injection/exceptions.py,sha256=RsWWiWwKSMU0vxXQqQSn6CKHLMrGu4SSzYUAy9OJRXk,626
13
+ injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ injection/integrations/blacksheep.py,sha256=82P_owhF3FKIJxxalnSic3AJnoOr1mkojkWMefpO6QI,731
15
+ injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ injection/testing/__init__.py,sha256=xglKmIJgg2j1wt8qWJ_TtGfFyKmn7xE7b8kQhD2yEkQ,864
17
+ injection/testing/__init__.pyi,sha256=_u95cJVHBkt69HUvnu2bbfYWmi7GOH_1qyFyvC1PxBk,518
18
+ injection/utils.py,sha256=_79aiciimZpuoUTz5lojKySUMMzpkU-e7SotiHIFTI8,676
19
+ python_injection-0.9.1.dist-info/METADATA,sha256=6vDRDhsWCG-FbwiHs-pvslfia8Fpe2n7hWJPoxJJbhg,3572
20
+ python_injection-0.9.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
21
+ python_injection-0.9.1.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- injection/__init__.py,sha256=Bf6S99E2srD3752xlJf3uAdiGIzY2YHOZafcwEiwY70,739
2
- injection/__init__.pyi,sha256=fNTW5TUZQmaxPooaa_vJ_nyR_-DqZ13hSWHh_TsdeOo,5913
3
- injection/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- injection/common/event.py,sha256=TvkFv-5zF_oUTPhh5U0BKD5HanvCJKHA0H7yceMRy5c,1261
5
- injection/common/invertible.py,sha256=BZnkDg_NZDsTXGca5w5Wg_nYE3oRO_Wlodi2XtE55ck,595
6
- injection/common/lazy.py,sha256=1C34uoG229Gl0DEUcD9-eQrL4K_oIofOLzdQ1SiY6rw,1401
7
- injection/common/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- injection/common/tools/threading.py,sha256=RAtzBFLVNJMflWIHxrP83fjafnFq8_JLgFoYQg8nVyE,182
9
- injection/common/tools/type.py,sha256=05fD5UkUI1kPoFWEjQz4j266SYfJQMK-Ti88JXNxb_M,1276
10
- injection/core/__init__.py,sha256=zuf0ubI2dHnbjn1059eduhS-ACIkkROa6-dhp10krh0,22
11
- injection/core/module.py,sha256=9QAYw5u8ULev3UWZCJ3R2dH9-xCqjc5e_9_19hrVWWw,20626
12
- injection/exceptions.py,sha256=f2lVSTAx-Nv89s0skn15y-sCkr656ROuWYs-XlrcEn8,683
13
- injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- injection/integrations/blacksheep.py,sha256=dFXzrxkJRy9z44CcwG0ROYshT3zUZTVyuQkRy390RvU,765
15
- injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- injection/utils.py,sha256=_79aiciimZpuoUTz5lojKySUMMzpkU-e7SotiHIFTI8,676
17
- python_injection-0.8.5.dist-info/METADATA,sha256=ZUrcGLYxHJC3IIwnBDJgsA3wlZ25zTNHeopIVWi4EHM,3672
18
- python_injection-0.8.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
19
- python_injection-0.8.5.dist-info/RECORD,,