Dynamically accessing attributes of provided objects.
See original GitHub issueHi, I recently needed to access an attribute of a provided object for constructing a new object. A minimal example would look like this
import random
from dependency_injector import containers, providers
class B:
def __init__(self):
self.val = random.randint(0, 10)
def __repr__(self):
return f"B({self.val})"
class A:
def __init__(self, b_val: int):
self.b_val = b_val
def __repr__(self):
return f"A({self.b_val})"
naively I tried to do
class MyContainer(containers.DeclarativeContainer):
b = providers.Singleton(B)
a = providers.Singleton(A, b.val)
def main() -> None:
container = MyContainer()
print(container.b())
print(container.a())
if __name__ == "__main__":
main()
which does not work, because of AttributeError: 'dependency_injector.providers.Singleton' object has no attribute 'val'
.
I was able to work around this, by using
class MyContainer(containers.DeclarativeContainer):
b = providers.Singleton(B)
b_val = providers.Callable(getattr, b, "val")
a = providers.Singleton(A, b_val)
However, I thought that it would be nice if dependency_injector
would provide this behavior out of the box.
My attempts at implementing a provider that has this behavior look like
class AttributeFactory(providers.Provider):
__slots__ = ('_factory',)
def __init__(self, *args, **kwargs):
self._factory = providers.Factory(*args, **kwargs)
super().__init__()
def __getattr__(self, item):
return providers.Callable(getattr, self._factory, item)
class MyContainer(containers.DeclarativeContainer):
b = AttributeFactory(B)
a = providers.Singleton(A, b.val)
However, this fails with TypeError: __init__() takes at least 1 positional argument (0 given)
because of some copying, that I can not really interpret.
I would be interested in hearing thoughts on this or if there are other ways to achieve this kind of attribute access.
Issue Analytics
- State:
- Created 3 years ago
- Comments:10 (10 by maintainers)
Top GitHub Comments
@rmk135 Glad I could contribute some idea. I never heard about TRIZ, but it sounds like an interesting read!
Great, let me know if I can contribute something. I believe the feature will make dependency injector extremely flexible, lowering the barrier for people adopting it.
@rmk135 I am amazed by the speed you implemented this. Thanks a lot!