python-injection 0.8.4.post1__tar.gz → 0.8.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.

Potentially problematic release.


This version of python-injection might be problematic. Click here for more details.

Files changed (20) hide show
  1. {python_injection-0.8.4.post1 → python_injection-0.8.5}/PKG-INFO +1 -1
  2. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/__init__.pyi +11 -11
  3. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/invertible.py +6 -6
  4. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/core/module.py +41 -33
  5. {python_injection-0.8.4.post1 → python_injection-0.8.5}/pyproject.toml +1 -1
  6. python_injection-0.8.4.post1/injection/common/queue.py +0 -63
  7. {python_injection-0.8.4.post1 → python_injection-0.8.5}/documentation/basic-usage.md +0 -0
  8. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/__init__.py +0 -0
  9. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/__init__.py +0 -0
  10. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/event.py +0 -0
  11. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/lazy.py +0 -0
  12. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/tools/__init__.py +0 -0
  13. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/tools/threading.py +0 -0
  14. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/common/tools/type.py +0 -0
  15. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/core/__init__.py +0 -0
  16. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/exceptions.py +0 -0
  17. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/integrations/__init__.py +0 -0
  18. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/integrations/blacksheep.py +0 -0
  19. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/py.typed +0 -0
  20. {python_injection-0.8.4.post1 → python_injection-0.8.5}/injection/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-injection
3
- Version: 0.8.4.post1
3
+ Version: 0.8.5
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
@@ -16,8 +16,8 @@ from typing import (
16
16
 
17
17
  from .common.invertible import Invertible
18
18
 
19
- _In_T = TypeVar("_In_T", covariant=False)
20
- _Co_T = TypeVar("_Co_T", covariant=True)
19
+ _T = TypeVar("_T")
20
+ _T_co = TypeVar("_T_co", covariant=True)
21
21
 
22
22
  default_module: Final[Module] = ...
23
23
 
@@ -88,24 +88,24 @@ class Module:
88
88
 
89
89
  def set_constant(
90
90
  self,
91
- instance: _In_T,
91
+ instance: _T,
92
92
  on: type | Iterable[type] | UnionType = ...,
93
93
  *,
94
94
  mode: InjectableMode | Literal["fallback", "normal", "override"] = ...,
95
- ) -> _In_T:
95
+ ) -> _T:
96
96
  """
97
97
  Function for registering a specific instance to be injected. This is useful for
98
98
  registering global variables. The difference with the singleton decorator is
99
99
  that no dependencies are resolved, so the module doesn't need to be locked.
100
100
  """
101
101
 
102
- def resolve(self, cls: type[_In_T]) -> _In_T:
102
+ def resolve(self, cls: type[_T]) -> _T:
103
103
  """
104
104
  Function used to retrieve an instance associated with the type passed in
105
105
  parameter or an exception will be raised.
106
106
  """
107
107
 
108
- def get_instance(self, cls: type[_In_T]) -> _In_T | None:
108
+ def get_instance(self, cls: type[_T]) -> _T | None:
109
109
  """
110
110
  Function used to retrieve an instance associated with the type passed in
111
111
  parameter or return `None`.
@@ -113,10 +113,10 @@ class Module:
113
113
 
114
114
  def get_lazy_instance(
115
115
  self,
116
- cls: type[_In_T],
116
+ cls: type[_T],
117
117
  *,
118
118
  cache: bool = ...,
119
- ) -> Invertible[_In_T | None]:
119
+ ) -> Invertible[_T | None]:
120
120
  """
121
121
  Function used to retrieve an instance associated with the type passed in
122
122
  parameter or `None`. Return a `Invertible` object. To access the instance
@@ -177,13 +177,13 @@ class ModulePriority(str, Enum):
177
177
  HIGH = ...
178
178
 
179
179
  @runtime_checkable
180
- class Injectable(Protocol[_Co_T]):
181
- def __init__(self, factory: Callable[[], _Co_T] = ..., /): ...
180
+ class Injectable(Protocol[_T_co]):
181
+ def __init__(self, factory: Callable[[], _T_co] = ..., /): ...
182
182
  @property
183
183
  def is_locked(self) -> bool: ...
184
184
  def unlock(self): ...
185
185
  @abstractmethod
186
- def get_instance(self) -> _Co_T: ...
186
+ def get_instance(self) -> _T_co: ...
187
187
 
188
188
  @final
189
189
  class InjectableMode(str, Enum):
@@ -5,19 +5,19 @@ from typing import Protocol, TypeVar, runtime_checkable
5
5
 
6
6
  __all__ = ("Invertible", "SimpleInvertible")
7
7
 
8
- _T = TypeVar("_T", covariant=True)
8
+ _T_co = TypeVar("_T_co", covariant=True)
9
9
 
10
10
 
11
11
  @runtime_checkable
12
- class Invertible(Protocol[_T]):
12
+ class Invertible(Protocol[_T_co]):
13
13
  @abstractmethod
14
- def __invert__(self) -> _T:
14
+ def __invert__(self) -> _T_co:
15
15
  raise NotImplementedError
16
16
 
17
17
 
18
18
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
19
- class SimpleInvertible(Invertible[_T]):
20
- callable: Callable[[], _T]
19
+ class SimpleInvertible(Invertible[_T_co]):
20
+ callable: Callable[[], _T_co]
21
21
 
22
- def __invert__(self) -> _T:
22
+ def __invert__(self) -> _T_co:
23
23
  return self.callable()
@@ -17,6 +17,7 @@ from dataclasses import dataclass, field
17
17
  from enum import Enum
18
18
  from functools import partialmethod, singledispatchmethod, update_wrapper
19
19
  from inspect import Signature, isclass
20
+ from queue import Queue
20
21
  from types import MethodType, UnionType
21
22
  from typing import (
22
23
  Any,
@@ -33,7 +34,6 @@ from typing import (
33
34
  from injection.common.event import Event, EventChannel, EventListener
34
35
  from injection.common.invertible import Invertible, SimpleInvertible
35
36
  from injection.common.lazy import Lazy, LazyMapping
36
- from injection.common.queue import LimitedQueue
37
37
  from injection.common.tools.threading import synchronized
38
38
  from injection.common.tools.type import find_types, format_type, get_origins
39
39
  from injection.exceptions import (
@@ -48,9 +48,8 @@ __all__ = ("Injectable", "Mode", "Module", "Priority")
48
48
 
49
49
  _logger = logging.getLogger(__name__)
50
50
 
51
- _In_T = TypeVar("_In_T", covariant=False)
52
- _Co_T = TypeVar("_Co_T", covariant=True)
53
-
51
+ _T = TypeVar("_T")
52
+ _T_co = TypeVar("_T_co", covariant=True)
54
53
 
55
54
  """
56
55
  Events
@@ -135,10 +134,10 @@ Injectables
135
134
 
136
135
 
137
136
  @runtime_checkable
138
- class Injectable(Protocol[_Co_T]):
137
+ class Injectable(Protocol[_T_co]):
139
138
  __slots__ = ()
140
139
 
141
- def __init__(self, __factory: Callable[[], _Co_T] = None, /):
140
+ def __init__(self, __factory: Callable[[], _T_co] = None, /):
142
141
  pass
143
142
 
144
143
  @property
@@ -149,23 +148,23 @@ class Injectable(Protocol[_Co_T]):
149
148
  return
150
149
 
151
150
  @abstractmethod
152
- def get_instance(self) -> _Co_T:
151
+ def get_instance(self) -> _T_co:
153
152
  raise NotImplementedError
154
153
 
155
154
 
156
155
  @dataclass(repr=False, frozen=True, slots=True)
157
- class BaseInjectable(Injectable[_In_T], ABC):
158
- factory: Callable[[], _In_T]
156
+ class BaseInjectable(Injectable[_T], ABC):
157
+ factory: Callable[[], _T]
159
158
 
160
159
 
161
- class NewInjectable(BaseInjectable[_In_T]):
160
+ class NewInjectable(BaseInjectable[_T]):
162
161
  __slots__ = ()
163
162
 
164
- def get_instance(self) -> _In_T:
163
+ def get_instance(self) -> _T:
165
164
  return self.factory()
166
165
 
167
166
 
168
- class SingletonInjectable(BaseInjectable[_In_T]):
167
+ class SingletonInjectable(BaseInjectable[_T]):
169
168
  __slots__ = ("__dict__",)
170
169
 
171
170
  __INSTANCE_KEY: ClassVar[str] = "$instance"
@@ -181,7 +180,7 @@ class SingletonInjectable(BaseInjectable[_In_T]):
181
180
  def unlock(self):
182
181
  self.cache.clear()
183
182
 
184
- def get_instance(self) -> _In_T:
183
+ def get_instance(self) -> _T:
185
184
  with suppress(KeyError):
186
185
  return self.cache[self.__INSTANCE_KEY]
187
186
 
@@ -193,8 +192,8 @@ class SingletonInjectable(BaseInjectable[_In_T]):
193
192
 
194
193
 
195
194
  @dataclass(repr=False, frozen=True, slots=True)
196
- class ShouldBeInjectable(Injectable[_In_T]):
197
- cls: type[_In_T]
195
+ class ShouldBeInjectable(Injectable[_T]):
196
+ cls: type[_T]
198
197
 
199
198
  def get_instance(self) -> NoReturn:
200
199
  raise InjectionError(f"`{format_type(self.cls)}` should be an injectable.")
@@ -210,7 +209,7 @@ class Broker(Protocol):
210
209
  __slots__ = ()
211
210
 
212
211
  @abstractmethod
213
- def __getitem__(self, cls: type[_In_T] | UnionType, /) -> Injectable[_In_T]:
212
+ def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
214
213
  raise NotImplementedError
215
214
 
216
215
  @abstractmethod
@@ -259,7 +258,7 @@ class Container(Broker):
259
258
  __records: dict[type, Record] = field(default_factory=dict, init=False)
260
259
  __channel: EventChannel = field(default_factory=EventChannel, init=False)
261
260
 
262
- def __getitem__(self, cls: type[_In_T] | UnionType, /) -> Injectable[_In_T]:
261
+ def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
263
262
  for cls in get_origins(cls):
264
263
  try:
265
264
  injectable, _ = self.__records[cls]
@@ -372,7 +371,7 @@ class Module(EventListener, Broker):
372
371
  def __post_init__(self):
373
372
  self.__container.add_listener(self)
374
373
 
375
- def __getitem__(self, cls: type[_In_T] | UnionType, /) -> Injectable[_In_T]:
374
+ def __getitem__(self, cls: type[_T] | UnionType, /) -> Injectable[_T]:
376
375
  for broker in self.__brokers:
377
376
  with suppress(KeyError):
378
377
  return broker[cls]
@@ -431,11 +430,11 @@ class Module(EventListener, Broker):
431
430
 
432
431
  def set_constant(
433
432
  self,
434
- instance: _In_T,
433
+ instance: _T,
435
434
  on: type | Iterable[type] | UnionType = (),
436
435
  *,
437
436
  mode: Mode | ModeStr = Mode.get_default(),
438
- ) -> _In_T:
437
+ ) -> _T:
439
438
  cls = type(instance)
440
439
  self.injectable(
441
440
  lambda: instance,
@@ -468,11 +467,11 @@ class Module(EventListener, Broker):
468
467
 
469
468
  return decorator(wrapped) if wrapped else decorator
470
469
 
471
- def resolve(self, cls: type[_In_T]) -> _In_T:
470
+ def resolve(self, cls: type[_T]) -> _T:
472
471
  injectable = self[cls]
473
472
  return injectable.get_instance()
474
473
 
475
- def get_instance(self, cls: type[_In_T]) -> _In_T | None:
474
+ def get_instance(self, cls: type[_T]) -> _T | None:
476
475
  try:
477
476
  return self.resolve(cls)
478
477
  except KeyError:
@@ -480,10 +479,10 @@ class Module(EventListener, Broker):
480
479
 
481
480
  def get_lazy_instance(
482
481
  self,
483
- cls: type[_In_T],
482
+ cls: type[_T],
484
483
  *,
485
484
  cache: bool = False,
486
- ) -> Invertible[_In_T | None]:
485
+ ) -> Invertible[_T | None]:
487
486
  if cache:
488
487
  return Lazy(lambda: self.get_instance(cls))
489
488
 
@@ -684,8 +683,10 @@ class InjectedFunction(EventListener):
684
683
  update_wrapper(self, wrapped, updated=())
685
684
  self.__dependencies = Dependencies.empty()
686
685
  self.__owner = None
687
- self.__setup_queue = LimitedQueue[Callable[[], Any]]()
688
- self.on_setup(self.__set_signature)
686
+
687
+ queue = Queue[Callable[[], Any]]()
688
+ queue.put_nowait(self.__set_signature)
689
+ self.__setup_queue = queue
689
690
 
690
691
  def __repr__(self) -> str: # pragma: no cover
691
692
  return repr(self.wrapped)
@@ -694,8 +695,12 @@ class InjectedFunction(EventListener):
694
695
  return str(self.wrapped)
695
696
 
696
697
  def __call__(self, /, *args, **kwargs) -> Any:
697
- for function in self.__setup_queue:
698
- function()
698
+ queue = self.__setup_queue
699
+
700
+ while not queue.empty():
701
+ setup = queue.get()
702
+ setup()
703
+ queue.task_done()
699
704
 
700
705
  arguments = self.bind(args, kwargs)
701
706
  return self.wrapped(*arguments.args, **arguments.kwargs)
@@ -753,7 +758,7 @@ class InjectedFunction(EventListener):
753
758
 
754
759
  def on_setup(self, wrapped: Callable[[], Any] = None, /):
755
760
  def decorator(wp):
756
- self.__setup_queue.add(wp)
761
+ self.__setup_queue.put(wp)
757
762
  return wp
758
763
 
759
764
  return decorator(wrapped) if wrapped else decorator
@@ -781,12 +786,15 @@ class InjectedFunction(EventListener):
781
786
  self.__update_vars(variables)
782
787
 
783
788
  def __update_vars(self, variables: Mapping[str, Any]):
784
- def is_dunder(var: str) -> bool:
785
- return var.startswith("__") and var.endswith("__")
786
-
787
- restricted_vars = frozenset(var for var in dir(self) if not is_dunder(var))
789
+ restricted_vars = frozenset(
790
+ var for var in dir(self) if not self.__is_dunder(var)
791
+ )
788
792
  vars(self).update(
789
793
  (var, value)
790
794
  for var, value in variables.items()
791
795
  if var not in restricted_vars
792
796
  )
797
+
798
+ @staticmethod
799
+ def __is_dunder(var: str) -> bool:
800
+ return var.startswith("__") and var.endswith("__")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-injection"
3
- version = "0.8.4.post1"
3
+ version = "0.8.5"
4
4
  description = "Fast and easy dependency injection framework."
5
5
  authors = ["remimd"]
6
6
  keywords = ["dependencies", "inject", "injection"]
@@ -1,63 +0,0 @@
1
- from abc import abstractmethod
2
- from collections import deque
3
- from collections.abc import Iterator
4
- from dataclasses import dataclass, field
5
- from typing import NoReturn, Protocol, TypeVar
6
-
7
- __all__ = ("LimitedQueue",)
8
-
9
- _T = TypeVar("_T")
10
-
11
-
12
- class Queue(Iterator[_T], Protocol):
13
- __slots__ = ()
14
-
15
- @abstractmethod
16
- def add(self, item: _T):
17
- raise NotImplementedError
18
-
19
-
20
- @dataclass(repr=False, frozen=True, slots=True)
21
- class SimpleQueue(Queue[_T]):
22
- __items: deque[_T] = field(default_factory=deque, init=False)
23
-
24
- def __next__(self) -> _T:
25
- try:
26
- return self.__items.popleft()
27
- except IndexError as exc:
28
- raise StopIteration from exc
29
-
30
- def add(self, item: _T):
31
- self.__items.append(item)
32
- return self
33
-
34
-
35
- class DeadQueue(Queue[_T]):
36
- __slots__ = ()
37
-
38
- def __bool__(self) -> bool:
39
- return False
40
-
41
- def __next__(self) -> NoReturn:
42
- raise StopIteration
43
-
44
- def add(self, item: _T) -> NoReturn:
45
- raise TypeError("Queue is dead.")
46
-
47
-
48
- @dataclass(repr=False, slots=True)
49
- class LimitedQueue(Queue[_T]):
50
- __state: Queue[_T] = field(default_factory=SimpleQueue)
51
-
52
- def __next__(self) -> _T:
53
- try:
54
- return next(self.__state)
55
- except StopIteration as exc:
56
- if self.__state:
57
- self.__state = DeadQueue()
58
-
59
- raise exc
60
-
61
- def add(self, item: _T):
62
- self.__state.add(item)
63
- return self