-
Notifications
You must be signed in to change notification settings - Fork 296
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
[Question] What does the @inject decorator do? #404
Comments
Hi @ecs-jnguyen , That's a very good question. My pleasure to provide an explanation. Decorator Why that's needed? The answer is in how wiring works. Wiring introspects a module and looks for any functions or methods that have Case 1 is closures: def foo():
@inject
def bar(x = Provide[...]): # no way to reach it with introspection
... Case 2 is replacing class decorators. The example of this is @click.command()
@click.option('-c', '--configuration-file', help='Configuration file path', default='config.yml')
@click.argument('test_key')
@inject # Registers it in wiring module before the reference is masked by click class
def cli(test_key, configuration_file, config: Config = Provider[Container.config]) -> None:
...
print(type(cli)) # Output: <class 'click.core.Command'> Case 3 is memorizing decorator. This is typical for web and api frameworks when defining the routes. Framework decorator memorizes a reference to the function before the wiring happens. Even when wiring passes later, other framework keeps reference to pre-wiring-decorated callable: from fastapi import APIRouter, Depends
router = APIRouter()
@router.get('/', response_model=Response)
@inject # Registers it in wiring module before router has memorized pre-decorated function
async def index(
query: Optional[str] = None,
limit: Optional[str] = None,
default_query: str = Depends(Provide[Container.config.default.query]),
default_limit: int = Depends(Provide[Container.config.default.limit.as_int()]),
search_service: SearchService = Depends(Provide[Container.search_service]),
):
... Early versions of the Dependency Injector |
@rmk135 Thank you for answering my question! I appreciate the time and effort you guys put into all this! |
No problems, thanks for asking. PS: When you say "you guys" it's actually only me for now. |
@rmk135 Sorry to message you after you closed the issue. I have 1 more quick question. I'm trying to find a way to use the Do you recommend initializing multiple containers and calling the
EDIT: I removed the |
Btw I edited the code. I just realized in my example the |
There's nothing bad in it, but I would recommend to gather everything in a single container. Wiring feature role is to ease the integration with other frameworks. Your own code typically could not use wiring. The idea is that you gather everything in the container and then use wiring to inject your components to the framework of your choice. That was an initial idea, but that's not a mandatory rule. You could have multiple containers and wire them to the any part of the code without any limitations. Btw, in case you face circular imports problem you can use wiring with string identifiers https://python-dependency-injector.ets-labs.org/wiring.html#strings-identifiers |
@rmk135 Thanks for getting back to me. using the 'string' identifiers should help. Hopefully i don't run into any circular dependencies lol |
I'm closing this issue. Open a new one if any help needed. |
Hi I am playing around with the dependency_injector library and I am trying to find out what the
@inject
decorator does. I have tried this sample program with and without the@inject
decorator and noticed no difference. Is the@inject
decorate necessary?The text was updated successfully, but these errors were encountered: