python-injection 0.9.4.post0__tar.gz → 0.9.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 (22) hide show
  1. {python_injection-0.9.4.post0 → python_injection-0.9.5}/PKG-INFO +3 -2
  2. {python_injection-0.9.4.post0 → python_injection-0.9.5}/documentation/basic-usage.md +2 -1
  3. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/__init__.pyi +1 -1
  4. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/tools/type.py +3 -3
  5. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/core/module.py +23 -22
  6. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/integrations/blacksheep.py +0 -1
  7. python_injection-0.9.5/injection/testing/__init__.py +35 -0
  8. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/testing/__init__.pyi +1 -1
  9. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/utils.py +13 -8
  10. {python_injection-0.9.4.post0 → python_injection-0.9.5}/pyproject.toml +1 -1
  11. python_injection-0.9.4.post0/injection/testing/__init__.py +0 -35
  12. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/__init__.py +0 -0
  13. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/__init__.py +0 -0
  14. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/event.py +0 -0
  15. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/invertible.py +0 -0
  16. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/lazy.py +0 -0
  17. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/tools/__init__.py +0 -0
  18. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/common/tools/threading.py +0 -0
  19. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/core/__init__.py +0 -0
  20. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/exceptions.py +0 -0
  21. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/integrations/__init__.py +0 -0
  22. {python_injection-0.9.4.post0 → python_injection-0.9.5}/injection/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-injection
3
- Version: 0.9.4.post0
3
+ Version: 0.9.5
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
@@ -59,7 +59,8 @@ from injection import set_constant
59
59
  class ServiceC:
60
60
  """ class implementation """
61
61
 
62
- service_c = set_constant(ServiceC())
62
+ service_c = ServiceC()
63
+ set_constant(service_c)
63
64
  ```
64
65
 
65
66
  ## Inject an instance
@@ -33,7 +33,8 @@ from injection import set_constant
33
33
  class ServiceC:
34
34
  """ class implementation """
35
35
 
36
- service_c = set_constant(ServiceC())
36
+ service_c = ServiceC()
37
+ set_constant(service_c)
37
38
  ```
38
39
 
39
40
  ## Inject an instance
@@ -101,7 +101,7 @@ class Module:
101
101
  on: TypeInfo[T] = ...,
102
102
  *,
103
103
  mode: InjectableMode | InjectableModeStr = ...,
104
- ) -> T:
104
+ ) -> Self:
105
105
  """
106
106
  Function for registering a specific instance to be injected. This is useful for
107
107
  registering global variables. The difference with the singleton decorator is
@@ -59,9 +59,9 @@ def analyze_types(*types: type | Any) -> Iterator[TypeReport[Any]]:
59
59
 
60
60
  def get_return_types(*args: TypeInfo[Any]) -> Iterator[type | UnionType]:
61
61
  for arg in args:
62
- origin = get_origin(arg) or arg
63
-
64
- if isinstance(origin, Iterable) and not isinstance(origin, type | str):
62
+ if isinstance(arg, Iterable) and not (
63
+ isinstance(arg, type | str) or isinstance(get_origin(arg), type)
64
+ ):
65
65
  inner_args = arg
66
66
 
67
67
  elif isfunction(arg):
@@ -66,7 +66,7 @@ Events
66
66
 
67
67
  @dataclass(frozen=True, slots=True)
68
68
  class ContainerEvent(Event, ABC):
69
- on_container: Container
69
+ container: Container
70
70
 
71
71
 
72
72
  @dataclass(frozen=True, slots=True)
@@ -85,7 +85,7 @@ class ContainerDependenciesUpdated(ContainerEvent):
85
85
 
86
86
  @dataclass(frozen=True, slots=True)
87
87
  class ModuleEvent(Event, ABC):
88
- on_module: Module
88
+ module: Module
89
89
 
90
90
 
91
91
  @dataclass(frozen=True, slots=True)
@@ -93,7 +93,7 @@ class ModuleEventProxy(ModuleEvent):
93
93
  event: Event
94
94
 
95
95
  def __str__(self) -> str:
96
- return f"`{self.on_module}` has propagated an event: {self.origin}"
96
+ return f"`{self.module}` has propagated an event: {self.origin}"
97
97
 
98
98
  @property
99
99
  def history(self) -> Iterator[Event]:
@@ -113,7 +113,7 @@ class ModuleAdded(ModuleEvent):
113
113
  priority: Priority
114
114
 
115
115
  def __str__(self) -> str:
116
- return f"`{self.on_module}` now uses `{self.module_added}`."
116
+ return f"`{self.module}` now uses `{self.module_added}`."
117
117
 
118
118
 
119
119
  @dataclass(frozen=True, slots=True)
@@ -121,7 +121,7 @@ class ModuleRemoved(ModuleEvent):
121
121
  module_removed: Module
122
122
 
123
123
  def __str__(self) -> str:
124
- return f"`{self.on_module}` no longer uses `{self.module_removed}`."
124
+ return f"`{self.module}` no longer uses `{self.module_removed}`."
125
125
 
126
126
 
127
127
  @dataclass(frozen=True, slots=True)
@@ -131,7 +131,7 @@ class ModulePriorityUpdated(ModuleEvent):
131
131
 
132
132
  def __str__(self) -> str:
133
133
  return (
134
- f"In `{self.on_module}`, the priority `{self.priority}` "
134
+ f"In `{self.module}`, the priority `{self.priority}` "
135
135
  f"has been applied to `{self.module_updated}`."
136
136
  )
137
137
 
@@ -265,7 +265,7 @@ class Container(Broker):
265
265
 
266
266
  def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
267
267
  for report in analyze_types(cls):
268
- for scoped_report in dict.fromkeys((report, report.no_args)):
268
+ for scoped_report in OrderedDict.fromkeys((report, report.no_args)):
269
269
  try:
270
270
  injectable, _ = self.__records[scoped_report]
271
271
  except KeyError:
@@ -302,7 +302,7 @@ class Container(Broker):
302
302
  if records:
303
303
  event = ContainerDependenciesUpdated(self, records.keys(), mode)
304
304
 
305
- with self.notify(event):
305
+ with self.dispatch(event):
306
306
  self.__records.update(records)
307
307
 
308
308
  return self
@@ -318,7 +318,7 @@ class Container(Broker):
318
318
  self.__channel.add_listener(listener)
319
319
  return self
320
320
 
321
- def notify(self, event: Event) -> ContextManager:
321
+ def dispatch(self, event: Event) -> ContextManager:
322
322
  return self.__channel.dispatch(event)
323
323
 
324
324
  def __prepare_reports_for_updating(
@@ -455,7 +455,7 @@ class Module(EventListener, Broker):
455
455
  on: TypeInfo[T] = (),
456
456
  *,
457
457
  mode: Mode | ModeStr = Mode.get_default(),
458
- ) -> T:
458
+ ) -> Self:
459
459
  cls = type(instance)
460
460
  self.injectable(
461
461
  lambda: instance,
@@ -463,7 +463,7 @@ class Module(EventListener, Broker):
463
463
  on=(cls, on),
464
464
  mode=mode,
465
465
  )
466
- return instance
466
+ return self
467
467
 
468
468
  def inject(
469
469
  self,
@@ -544,7 +544,7 @@ class Module(EventListener, Broker):
544
544
  priority = Priority(priority)
545
545
  event = ModuleAdded(self, module, priority)
546
546
 
547
- with self.notify(event):
547
+ with self.dispatch(event):
548
548
  self.__modules[module] = None
549
549
  self.__move_module(module, priority)
550
550
  module.add_listener(self)
@@ -555,7 +555,7 @@ class Module(EventListener, Broker):
555
555
  event = ModuleRemoved(self, module)
556
556
 
557
557
  with suppress(KeyError):
558
- with self.notify(event):
558
+ with self.dispatch(event):
559
559
  self.__modules.pop(module)
560
560
  module.remove_listener(self)
561
561
 
@@ -576,7 +576,7 @@ class Module(EventListener, Broker):
576
576
  priority = Priority(priority)
577
577
  event = ModulePriorityUpdated(self, module, priority)
578
578
 
579
- with self.notify(event):
579
+ with self.dispatch(event):
580
580
  self.__move_module(module, priority)
581
581
 
582
582
  return self
@@ -602,15 +602,20 @@ class Module(EventListener, Broker):
602
602
 
603
603
  def on_event(self, event: Event, /) -> ContextManager:
604
604
  self_event = ModuleEventProxy(self, event)
605
- return self.notify(self_event)
605
+ return self.dispatch(self_event)
606
606
 
607
607
  @contextmanager
608
- def notify(self, event: Event):
608
+ def dispatch(self, event: Event):
609
609
  self.__check_locking()
610
610
 
611
611
  with self.__channel.dispatch(event):
612
612
  yield
613
- self.__send_debug(event)
613
+ message = str(event)
614
+ self.__debug(message)
615
+
616
+ def __debug(self, message: object):
617
+ for logger in tuple(self.__loggers):
618
+ logger.debug(message)
614
619
 
615
620
  def __check_locking(self):
616
621
  if self.is_locked:
@@ -626,10 +631,6 @@ class Module(EventListener, Broker):
626
631
  f"`{module}` can't be found in the modules used by `{self}`."
627
632
  ) from exc
628
633
 
629
- def __send_debug(self, message: object):
630
- for logger in tuple(self.__loggers):
631
- logger.debug(message)
632
-
633
634
  @classmethod
634
635
  def from_name(cls, name: str) -> Self:
635
636
  with suppress(KeyError):
@@ -816,7 +817,7 @@ class InjectedFunction(EventListener):
816
817
  @contextmanager
817
818
  def _(self, event: ModuleEvent, /):
818
819
  yield
819
- self.update(event.on_module)
820
+ self.update(event.module)
820
821
 
821
822
  def __setup(self):
822
823
  queue = self.__setup_queue
@@ -22,7 +22,6 @@ class InjectionServices(ContainerProtocol):
22
22
 
23
23
  def register(self, obj_type: type | Any, *args, **kwargs):
24
24
  self.__module.injectable(obj_type)
25
- return self
26
25
 
27
26
  def resolve[T](self, obj_type: type[T] | Any, *args, **kwargs) -> T:
28
27
  return self.__module.find_instance(obj_type)
@@ -0,0 +1,35 @@
1
+ from contextlib import contextmanager
2
+ from functools import partial
3
+
4
+ from injection import Module, ModulePriority, mod
5
+
6
+ __all__ = (
7
+ "set_test_constant",
8
+ "should_be_test_injectable",
9
+ "test_injectable",
10
+ "test_singleton",
11
+ "use_test_injectables",
12
+ )
13
+
14
+
15
+ tmod = partial(mod, "testing")
16
+
17
+ set_test_constant = tmod().set_constant
18
+ should_be_test_injectable = tmod().should_be_injectable
19
+ test_injectable = tmod().injectable
20
+ test_singleton = tmod().singleton
21
+
22
+
23
+ @contextmanager
24
+ def use_test_injectables(*, module: Module = None, test_module: Module = None):
25
+ module = module or mod()
26
+ test_module = test_module or tmod()
27
+
28
+ for m in (module, test_module):
29
+ m.unlock()
30
+
31
+ del m
32
+
33
+ with module.use_temporarily(test_module, priority=ModulePriority.HIGH):
34
+ yield
35
+ module.unlock()
@@ -11,7 +11,7 @@ test_singleton = _.singleton
11
11
 
12
12
  def use_test_injectables(
13
13
  *,
14
- on: Module = ...,
14
+ module: Module = ...,
15
15
  test_module: Module = ...,
16
16
  ) -> ContextManager | ContextDecorator:
17
17
  """
@@ -1,4 +1,4 @@
1
- from collections.abc import Callable
1
+ from collections.abc import Callable, Iterator
2
2
  from importlib import import_module
3
3
  from pkgutil import walk_packages
4
4
  from types import ModuleType
@@ -6,7 +6,10 @@ from types import ModuleType
6
6
  __all__ = ("load_package",)
7
7
 
8
8
 
9
- def load_package(package: ModuleType | str, predicate: Callable[[str], bool] = None):
9
+ def load_package(
10
+ package: ModuleType | str,
11
+ predicate: Callable[[str], bool] = lambda module_name: True,
12
+ ) -> tuple[ModuleType, ...]:
10
13
  """
11
14
  Function for importing all modules in a Python package.
12
15
  Pass the `predicate` parameter if you want to filter the modules to be imported.
@@ -15,6 +18,13 @@ def load_package(package: ModuleType | str, predicate: Callable[[str], bool] = N
15
18
  if isinstance(package, str):
16
19
  package = import_module(package)
17
20
 
21
+ return tuple(__iter_modules(package, predicate))
22
+
23
+
24
+ def __iter_modules(
25
+ package: ModuleType,
26
+ predicate: Callable[[str], bool],
27
+ ) -> Iterator[ModuleType]:
18
28
  try:
19
29
  path = package.__path__
20
30
  except AttributeError as exc:
@@ -22,15 +32,10 @@ def load_package(package: ModuleType | str, predicate: Callable[[str], bool] = N
22
32
  "Package has no `__path__` attribute, as it's probably a module."
23
33
  ) from exc
24
34
 
25
- if predicate is None:
26
-
27
- def predicate(_: str) -> bool:
28
- return True
29
-
30
35
  for info in walk_packages(path=path, prefix=f"{package.__name__}."):
31
36
  name = info.name
32
37
 
33
38
  if info.ispkg or not predicate(name):
34
39
  continue
35
40
 
36
- import_module(name)
41
+ yield import_module(name)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-injection"
3
- version = "0.9.4.post0"
3
+ version = "0.9.5"
4
4
  description = "Fast and easy dependency injection framework."
5
5
  license = "MIT"
6
6
  authors = ["remimd"]
@@ -1,35 +0,0 @@
1
- from contextlib import contextmanager
2
- from functools import partial
3
-
4
- from injection import Module, ModulePriority, mod
5
-
6
- __all__ = (
7
- "set_test_constant",
8
- "should_be_test_injectable",
9
- "test_injectable",
10
- "test_singleton",
11
- "use_test_injectables",
12
- )
13
-
14
-
15
- testing_mod = partial(mod, "testing")
16
-
17
- set_test_constant = testing_mod().set_constant
18
- should_be_test_injectable = testing_mod().should_be_injectable
19
- test_injectable = testing_mod().injectable
20
- test_singleton = testing_mod().singleton
21
-
22
-
23
- @contextmanager
24
- def use_test_injectables(*, on: Module = None, test_module: Module = None):
25
- on = on or mod()
26
- test_module = test_module or testing_mod()
27
-
28
- for module in (on, test_module):
29
- module.unlock()
30
-
31
- del module
32
-
33
- with on.use_temporarily(test_module, priority=ModulePriority.HIGH):
34
- yield
35
- on.unlock()