anydi 0.33.0__py3-none-any.whl → 0.33.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.
anydi/_container.py CHANGED
@@ -25,7 +25,7 @@ from ._logger import logger
25
25
  from ._module import Module, ModuleRegistry
26
26
  from ._provider import Provider
27
27
  from ._scanner import Scanner
28
- from ._types import AnyInterface, Interface, Scope, TestInterface, is_marker
28
+ from ._types import AnyInterface, DependencyWrapper, Interface, Scope, is_marker
29
29
  from ._utils import get_full_qualname, get_typed_parameters, is_builtin_type
30
30
 
31
31
  T = TypeVar("T", bound=Any)
@@ -371,28 +371,6 @@ class Container:
371
371
  self._patch_test_resolver(instance)
372
372
  return cast(T, instance)
373
373
 
374
- def _patch_test_resolver(self, instance: Any) -> None:
375
- """Patch the test resolver for the instance."""
376
-
377
- def _resolver(_self: Any, _name: str) -> Any:
378
- try:
379
- test_interfaces = object.__getattribute__(_self, "__test_interfaces__")
380
- except AttributeError:
381
- test_interfaces = {
382
- name: value.interface
383
- for name, value in object.__getattribute__(
384
- _self, "__dict__"
385
- ).items()
386
- if isinstance(value, TestInterface)
387
- }
388
- object.__setattr__(_self, "__test_interfaces__", test_interfaces)
389
- if _name in test_interfaces:
390
- return self.resolve(test_interfaces[_name])
391
- return object.__getattribute__(_self, _name)
392
-
393
- if hasattr(instance, "__class__") and not is_builtin_type(instance.__class__):
394
- instance.__class__.__getattribute__ = _resolver
395
-
396
374
  @overload
397
375
  async def aresolve(self, interface: Interface[T]) -> T: ...
398
376
 
@@ -411,6 +389,29 @@ class Container:
411
389
  self._patch_test_resolver(instance)
412
390
  return cast(T, instance)
413
391
 
392
+ def _patch_test_resolver(self, instance: Any) -> None:
393
+ """Patch the test resolver for the instance."""
394
+ if not hasattr(instance, "__dict__"):
395
+ return
396
+
397
+ wrapped = {
398
+ name: value.interface
399
+ for name, value in instance.__dict__.items()
400
+ if isinstance(value, DependencyWrapper)
401
+ }
402
+
403
+ # Custom resolver function
404
+ def _resolver(_self: Any, _name: str) -> Any:
405
+ if _name in wrapped:
406
+ # Resolve the dependency if it's wrapped
407
+ return self.resolve(wrapped[_name])
408
+ # Fall back to default behavior
409
+ return object.__getattribute__(_self, _name)
410
+
411
+ # Apply the patched resolver if wrapped attributes exist
412
+ if wrapped:
413
+ instance.__class__.__getattribute__ = _resolver
414
+
414
415
  def is_resolved(self, interface: AnyInterface) -> bool:
415
416
  """Check if an instance by interface exists."""
416
417
  try:
anydi/_context.py CHANGED
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any, Callable, ClassVar
9
9
  from typing_extensions import Self, final
10
10
 
11
11
  from ._provider import CallableKind, Provider
12
- from ._types import AnyInterface, Scope, TestInterface, is_event_type
12
+ from ._types import AnyInterface, DependencyWrapper, Scope, is_event_type
13
13
  from ._utils import get_full_qualname, run_async
14
14
 
15
15
  if TYPE_CHECKING:
@@ -99,7 +99,9 @@ class ScopedContext(abc.ABC):
99
99
  instance = parameter.default
100
100
  else:
101
101
  if self.container.testing:
102
- instance = TestInterface(interface=parameter.annotation)
102
+ instance = DependencyWrapper(
103
+ interface=parameter.annotation, instance=instance
104
+ )
103
105
  if parameter.kind == parameter.POSITIONAL_ONLY:
104
106
  args.append(instance)
105
107
  else:
@@ -127,7 +129,9 @@ class ScopedContext(abc.ABC):
127
129
  instance = parameter.default
128
130
  else:
129
131
  if self.container.testing:
130
- instance = TestInterface(interface=parameter.annotation)
132
+ instance = DependencyWrapper(
133
+ interface=parameter.annotation, instance=instance
134
+ )
131
135
  if parameter.kind == parameter.POSITIONAL_ONLY:
132
136
  args.append(instance)
133
137
  else:
anydi/_types.py CHANGED
@@ -39,5 +39,11 @@ def is_event_type(obj: Any) -> bool:
39
39
 
40
40
 
41
41
  @dataclass(frozen=True)
42
- class TestInterface:
42
+ class DependencyWrapper:
43
43
  interface: type[Any]
44
+ instance: Any
45
+
46
+ def __getattribute__(self, name: str) -> Any:
47
+ if name in {"interface", "instance"}:
48
+ return object.__getattribute__(self, name)
49
+ return getattr(self.instance, name)
@@ -105,8 +105,10 @@ def _anydi_inject(
105
105
 
106
106
  try:
107
107
  request.node.funcargs[argname] = container.resolve(interface)
108
- except Exception: # noqa
109
- logger.warning(f"Failed to resolve dependency for argument '{argname}'.")
108
+ except Exception as exc:
109
+ logger.warning(
110
+ f"Failed to resolve dependency for argument '{argname}'.", exc_info=exc
111
+ )
110
112
  _anydi_unresolved.append(interface)
111
113
 
112
114
 
@@ -131,6 +133,8 @@ async def _anydi_ainject(
131
133
 
132
134
  try:
133
135
  request.node.funcargs[argname] = await container.aresolve(interface)
134
- except Exception: # noqa
135
- logger.warning(f"Failed to resolve dependency for argument '{argname}'.")
136
+ except Exception as exc:
137
+ logger.warning(
138
+ f"Failed to resolve dependency for argument '{argname}'.", exc_info=exc
139
+ )
136
140
  _anydi_unresolved.append(interface)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: anydi
3
- Version: 0.33.0
3
+ Version: 0.33.1
4
4
  Summary: Dependency Injection library
5
5
  Home-page: https://github.com/antonrh/anydi
6
6
  License: MIT
@@ -1,11 +1,11 @@
1
1
  anydi/__init__.py,sha256=EsR-HiMe8cWS9PQbY23ibc91STK1WTn02DFMPV-TNU4,509
2
- anydi/_container.py,sha256=M1V7OMYp1BGSj0RQInS6xXYi3HgDGQ9CwjDezvC-fQc,21538
3
- anydi/_context.py,sha256=vBbL0POdkdL-kr2CEp35gQvzIBlFN2q7-wCNhr6gJqg,12708
2
+ anydi/_container.py,sha256=shefN3SuhmPBzU6gxV-YRGJlz-m8Nv5RJ-T93veSxgE,21389
3
+ anydi/_context.py,sha256=6Veqt15Tp4DfOzppUOIBaymosicYUWMeSa1b7ZAdtxw,12866
4
4
  anydi/_logger.py,sha256=UpubJUnW83kffFxkhUlObm2DmZX1Pjqoz9YFKS-JOPg,52
5
5
  anydi/_module.py,sha256=cgojC7Z7oMtsUnkfSc65cRYOfZ8Q6KwjusNJzx_VSbk,2729
6
6
  anydi/_provider.py,sha256=w_GnRo324aqNORRJwuURexA54c1M3smj34Q8EaV0QGE,6213
7
7
  anydi/_scanner.py,sha256=F2sHgJvkRYXYnu4F5iSrnIPVzwnNeS7tRPXziirh4NI,4898
8
- anydi/_types.py,sha256=GK6grYnmcCQODhtDvqn224IU0FXqV9Grm6oj4MDQCPY,902
8
+ anydi/_types.py,sha256=90xdbH2NrFXbridFf9mjOknhcXMW5L0jm92zP_LvKrg,1120
9
9
  anydi/_utils.py,sha256=guw4sFCvsisJmneKWlZi18YDYll_CjlO_f2cH97rDFQ,3280
10
10
  anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  anydi/ext/_utils.py,sha256=U6sRqWzccWUu7eMhbXX1NrwcaxitQF9cO1KxnKF37gw,2566
@@ -21,12 +21,12 @@ anydi/ext/django/ninja/_signature.py,sha256=2cSzKxBIxXLqtwNuH6GSlmjVJFftoGmleWfy
21
21
  anydi/ext/fastapi.py,sha256=AEL3ubu-LxUPHMMt1YIn3En_JZC7nyBKmKxmhka3O3c,2436
22
22
  anydi/ext/faststream.py,sha256=qXnNGvAqWWp9kbhbQUE6EF_OPUiYQmtOH211_O7BI_0,1898
23
23
  anydi/ext/pydantic_settings.py,sha256=8IXXLuG_OvKbvKlBkBRQUHcXgbTpgQUxeWyoMcRIUQM,1488
24
- anydi/ext/pytest_plugin.py,sha256=Df0pFgAOk-44UFsdZGAOSxElJTJLchs4sk2UZuV-KVk,4212
24
+ anydi/ext/pytest_plugin.py,sha256=3x_ZYFcLp4ZCRrs7neoohmWz56O9ydm92jxi_LnyD7w,4298
25
25
  anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  anydi/ext/starlette/middleware.py,sha256=PKip_omFZDgg7h2OY-nnV2OIS1MbbmrrOJBwG7_Peuw,793
27
27
  anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- anydi-0.33.0.dist-info/LICENSE,sha256=V6rU8a8fv6o2jQ-7ODHs0XfDFimot8Q6Km6CylRIDTo,1069
29
- anydi-0.33.0.dist-info/METADATA,sha256=NASeDNxy6DOKFk8hNXO7QAnOmWLgqFvJ0qNK8qlL7BE,5112
30
- anydi-0.33.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
- anydi-0.33.0.dist-info/entry_points.txt,sha256=GmQblwzxFg42zva1HyBYJJ7TvrTIcSAGBHmyi3bvsi4,42
32
- anydi-0.33.0.dist-info/RECORD,,
28
+ anydi-0.33.1.dist-info/LICENSE,sha256=V6rU8a8fv6o2jQ-7ODHs0XfDFimot8Q6Km6CylRIDTo,1069
29
+ anydi-0.33.1.dist-info/METADATA,sha256=u-YkBHTqAbah4ytfw7CXHEUNDVyjhBFUwD2dV8z84Jc,5112
30
+ anydi-0.33.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
+ anydi-0.33.1.dist-info/entry_points.txt,sha256=GmQblwzxFg42zva1HyBYJJ7TvrTIcSAGBHmyi3bvsi4,42
32
+ anydi-0.33.1.dist-info/RECORD,,
File without changes