Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject dependency into a class attr #411

Closed
brunopereira27 opened this issue Feb 27, 2021 · 6 comments
Closed

Inject dependency into a class attr #411

brunopereira27 opened this issue Feb 27, 2021 · 6 comments
Assignees
Labels

Comments

@brunopereira27
Copy link

Hello,

Sorry if this question already has been answered somewhere but I went through the doc extensively and couldn't find anything.

I would like to inject a dependency for a class attribute, but couldn't find any way of doing it.

Something similar from python-inject:

class User(object):
    cache = inject.attr(Cache)

Thanks for your help

@rmk135 rmk135 self-assigned this Feb 27, 2021
@rmk135
Copy link
Member

rmk135 commented Feb 27, 2021

Hello @brunopereira27 ,

You can do it with Factory provider:

cache_provider = providers.Singleton(Cache)

user_factory = providers.Factory(User)
user.add_attributes(cache=cache_provider)

user = user_factory()
assert isinstance(user.cache, Cache)

You didn't find it because I didn't document that. I'm sorry about that. I already have a backlog item to update documentation.

@rmk135
Copy link
Member

rmk135 commented Feb 27, 2021

The same works with Singleton provider btw.

@brunopereira27
Copy link
Author

Thanks for your quick answer!

As a consequence, I cannot provide a class attribute is that class is not created through a factory or as a singleton? Isn't there a way to provide a factory to the init function of a class?

@rmk135
Copy link
Member

rmk135 commented Feb 28, 2021

Few things:


  1. You asked:

Isn't there a way to provide a factory to the init function of a class?

Yes. You can use .provider attribute when specify an injection:

cache = providers.Singleton(Cache)

user_factory = providers.Factory(
    User,
    cache=cache.provider,  # This will inject cache provider instead of Cache instance
)

user = user_factory()
asseert user.cache_provider is cache_provider
assert isinstance(user.cache(), Cache)

  1. The closest feature to the initial your initial example is wiring. With wiring you can make an injection into functions and methods. Here is how initial example will look like with wiring:
class User(object):

    def __init__(self, cache=Provider[Container.cache]):
        ...

You also need to have a container and call container.wire(). You can read more about this here: https://python-dependency-injector.ets-labs.org/wiring.html


Current wiring can't make attribute injections, but I could upgrade it. Here is a prototype how it would look like:

class User(object):
    cache = Provider[Container.cache]

Also you could use string identifiers to do not pull a container:

class User(object):
    cache = Provider['cache']

I started working on it. Will probably take a few more days.

How does it look to you?

@rmk135 rmk135 added feature and removed question labels Feb 28, 2021
@rmk135
Copy link
Member

rmk135 commented Mar 1, 2021

I started working on it. Will probably take a few more days.

Done in version 4.28.0. Docs: https://python-dependency-injector.ets-labs.org/wiring.html#making-injections-into-modules-and-class-attributes

@rmk135
Copy link
Member

rmk135 commented Mar 2, 2021

Closing this issue. Feel free to comment if anything.

@rmk135 rmk135 closed this as completed Mar 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants