python-injection 0.25.13__tar.gz → 0.25.15__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 (31) hide show
  1. {python_injection-0.25.13 → python_injection-0.25.15}/PKG-INFO +1 -1
  2. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/type.py +6 -6
  3. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/injectables.py +5 -26
  4. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/module.py +7 -7
  5. {python_injection-0.25.13 → python_injection-0.25.15}/injection/loaders.py +5 -2
  6. {python_injection-0.25.13 → python_injection-0.25.15}/pyproject.toml +1 -1
  7. {python_injection-0.25.13 → python_injection-0.25.15}/.gitignore +0 -0
  8. {python_injection-0.25.13 → python_injection-0.25.15}/LICENSE +0 -0
  9. {python_injection-0.25.13 → python_injection-0.25.15}/docs/index.md +0 -0
  10. {python_injection-0.25.13 → python_injection-0.25.15}/injection/__init__.py +0 -0
  11. {python_injection-0.25.13 → python_injection-0.25.15}/injection/__init__.pyi +0 -0
  12. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/__init__.py +0 -0
  13. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/asfunction.py +0 -0
  14. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/__init__.py +0 -0
  15. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/asynchronous.py +0 -0
  16. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/event.py +0 -0
  17. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/invertible.py +0 -0
  18. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/lazy.py +0 -0
  19. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/common/threading.py +0 -0
  20. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/descriptors.py +0 -0
  21. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/locator.py +0 -0
  22. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/scope.py +0 -0
  23. {python_injection-0.25.13 → python_injection-0.25.15}/injection/_core/slots.py +0 -0
  24. {python_injection-0.25.13 → python_injection-0.25.15}/injection/entrypoint.py +0 -0
  25. {python_injection-0.25.13 → python_injection-0.25.15}/injection/exceptions.py +0 -0
  26. {python_injection-0.25.13 → python_injection-0.25.15}/injection/ext/__init__.py +0 -0
  27. {python_injection-0.25.13 → python_injection-0.25.15}/injection/ext/fastapi.py +0 -0
  28. {python_injection-0.25.13 → python_injection-0.25.15}/injection/ext/fastapi.pyi +0 -0
  29. {python_injection-0.25.13 → python_injection-0.25.15}/injection/py.typed +0 -0
  30. {python_injection-0.25.13 → python_injection-0.25.15}/injection/testing/__init__.py +0 -0
  31. {python_injection-0.25.13 → python_injection-0.25.15}/injection/testing/__init__.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-injection
3
- Version: 0.25.13
3
+ Version: 0.25.15
4
4
  Summary: Dead-simple dependency injection framework for Python.
5
5
  Project-URL: Documentation, https://python-injection.remimd.dev
6
6
  Project-URL: Repository, https://github.com/100nm/python-injection
@@ -28,14 +28,14 @@ type TypeInfo[T] = (
28
28
  )
29
29
 
30
30
 
31
- def get_return_hint[T](function: Callable[..., T]) -> InputType[T] | None:
31
+ def get_return_type[T](function: Callable[..., T]) -> Any | None:
32
32
  return get_type_hints(function).get("return")
33
33
 
34
34
 
35
- def get_yield_hints[T](
35
+ def get_yield_types[T](
36
36
  function: Callable[..., Iterator[T]] | Callable[..., AsyncIterator[T]],
37
- ) -> tuple[InputType[T]] | tuple[()]:
38
- return_type = get_return_hint(function)
37
+ ) -> tuple[Any] | tuple[()]:
38
+ return_type = get_return_type(function)
39
39
 
40
40
  if get_origin(return_type) in (
41
41
  AsyncGenerator,
@@ -62,8 +62,8 @@ def iter_flat_types(*args: Any) -> Iterator[Any]:
62
62
 
63
63
  def iter_return_types(*args: Any) -> Iterator[Any]:
64
64
  for arg in args:
65
- if isfunction(arg) and (return_type := get_return_hint(arg)):
66
- yield from iter_return_types(return_type)
65
+ if isfunction(arg) and (return_type := get_return_type(arg)):
66
+ yield return_type
67
67
 
68
68
  else:
69
69
  yield arg
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
- from collections.abc import Awaitable, Callable, Iterator, MutableMapping
3
- from contextlib import contextmanager, suppress
2
+ from collections.abc import Awaitable, Callable, MutableMapping
3
+ from contextlib import suppress
4
4
  from dataclasses import dataclass, field
5
5
  from functools import partial
6
6
  from typing import (
@@ -53,13 +53,11 @@ class TransientInjectable[T](Injectable[T]):
53
53
 
54
54
 
55
55
  class CacheLogic[T]:
56
- __slots__ = ("__is_instantiating", "__semaphore")
56
+ __slots__ = ("__semaphore",)
57
57
 
58
- __is_instantiating: bool
59
58
  __semaphore: AsyncContextManager[Any]
60
59
 
61
60
  def __init__(self) -> None:
62
- self.__is_instantiating = False
63
61
  self.__semaphore = AsyncSemaphore(1)
64
62
 
65
63
  async def aget_or_create[K](
@@ -68,14 +66,11 @@ class CacheLogic[T]:
68
66
  key: K,
69
67
  factory: Callable[..., Awaitable[T]],
70
68
  ) -> T:
71
- self.__fail_if_instantiating()
72
69
  async with self.__semaphore:
73
70
  with suppress(KeyError):
74
71
  return cache[key]
75
72
 
76
- with self.__instantiating():
77
- instance = await factory()
78
-
73
+ instance = await factory()
79
74
  cache[key] = instance
80
75
 
81
76
  return instance
@@ -86,29 +81,13 @@ class CacheLogic[T]:
86
81
  key: K,
87
82
  factory: Callable[..., T],
88
83
  ) -> T:
89
- self.__fail_if_instantiating()
90
84
  with suppress(KeyError):
91
85
  return cache[key]
92
86
 
93
- with self.__instantiating():
94
- instance = factory()
95
-
87
+ instance = factory()
96
88
  cache[key] = instance
97
89
  return instance
98
90
 
99
- def __fail_if_instantiating(self) -> None:
100
- if self.__is_instantiating:
101
- raise RecursionError("Recursive call detected during instantiation.")
102
-
103
- @contextmanager
104
- def __instantiating(self) -> Iterator[None]:
105
- self.__is_instantiating = True
106
-
107
- try:
108
- yield
109
- finally:
110
- self.__is_instantiating = False
111
-
112
91
 
113
92
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
114
93
  class SingletonInjectable[T](Injectable[T]):
@@ -52,7 +52,7 @@ from injection._core.common.threading import get_lock
52
52
  from injection._core.common.type import (
53
53
  InputType,
54
54
  TypeInfo,
55
- get_yield_hints,
55
+ get_yield_types,
56
56
  iter_flat_types,
57
57
  iter_return_types,
58
58
  )
@@ -264,14 +264,14 @@ class Module(EventListener, InjectionProvider): # type: ignore[misc]
264
264
  if isasyncgenfunction(wrapped):
265
265
  ctx = _ScopedContext(
266
266
  cls=AsyncCMScopedInjectable,
267
- hints=() if ignore_type_hint else get_yield_hints(wrapped),
267
+ hints=() if ignore_type_hint else get_yield_types(wrapped),
268
268
  wrapper=asynccontextmanager(wrapped),
269
269
  )
270
270
 
271
271
  elif isgeneratorfunction(wrapped):
272
272
  ctx = _ScopedContext(
273
273
  cls=CMScopedInjectable,
274
- hints=() if ignore_type_hint else get_yield_hints(wrapped),
274
+ hints=() if ignore_type_hint else get_yield_types(wrapped),
275
275
  wrapper=contextmanager(wrapped),
276
276
  )
277
277
 
@@ -713,19 +713,19 @@ class Module(EventListener, InjectionProvider): # type: ignore[misc]
713
713
  return cls.from_name("__default__")
714
714
 
715
715
  @staticmethod
716
- def __build_key_types(input_cls: Any) -> frozenset[Any]:
716
+ def __build_key_types(input_class: Any) -> frozenset[Any]:
717
717
  config = MatchingTypesConfig(ignore_none=True)
718
718
  return frozenset(
719
719
  matching_type
720
- for cls in iter_flat_types(input_cls)
720
+ for cls in iter_flat_types(input_class)
721
721
  for return_type in iter_return_types(cls)
722
722
  for matching_type in iter_matching_types(return_type, config)
723
723
  )
724
724
 
725
725
  @staticmethod
726
- def __matching_key_types(input_cls: Any) -> tuple[Any, ...]:
726
+ def __matching_key_types(input_class: Any) -> tuple[Any, ...]:
727
727
  config = MatchingTypesConfig(with_origin=True, with_type_alias_value=True)
728
- return matching_types(input_cls, config)
728
+ return matching_types(input_class, config)
729
729
 
730
730
 
731
731
  def mod(name: str | None = None, /) -> Module:
@@ -150,8 +150,11 @@ class ProfileLoader:
150
150
  return not self.module_subsets
151
151
 
152
152
  def required_module_names(self, name: str | None = None, /) -> frozenset[str]:
153
- names = {n for n in (self.module.name, name) if n is not None}
154
- subsets = (self.__walk_subsets_for(name) for name in names)
153
+ subsets = (
154
+ self.__walk_subsets_for(module_name)
155
+ for module_name in (self.module.name, name)
156
+ if module_name is not None
157
+ )
155
158
  return frozenset(itertools.chain.from_iterable(subsets))
156
159
 
157
160
  def init(self) -> Self:
@@ -24,7 +24,7 @@ test = [
24
24
 
25
25
  [project]
26
26
  name = "python-injection"
27
- version = "0.25.13"
27
+ version = "0.25.15"
28
28
  description = "Dead-simple dependency injection framework for Python."
29
29
  license = "MIT"
30
30
  license-files = ["LICENSE"]