question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] What does the @inject decorator do?

See original GitHub issue

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?

import sys
import uuid

from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide


class Service:
    def __init__(self):
        self.uuid = uuid.uuid4()


class Container(containers.DeclarativeContainer):

    service = providers.Factory(Service)


@inject # Commenting this out has no effect on the program
def main(service: Service = Provide[Container.service]) -> None:
    print(service.uuid)


if __name__ == '__main__':
    container = Container()
    container.wire(modules=[sys.modules[__name__]])

    main()

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

9reactions
rmk135commented, Feb 24, 2021

Hi @ecs-jnguyen ,

That’s a very good question. My pleasure to provide an explanation.

Decorator @inject registers functions and methods in wiring module.

Why that’s needed? The answer is in how wiring works. Wiring introspects a module and looks for any functions or methods that have Provide markers. That works fine, but there are some cases when it’s impossible to introspect properly.

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 library. Its decorator is class-based. This class based decorator hides the actual callable in the internals. No guarantee that it can be introspected:

@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 4 didn’t have @inject decorator. It worked fine when framework could introspect. I’ve added @inject after discovered cases above. To not confuse people with the rules, I recommend to use @inject all the time. It gives a guarantee that wiring will find the markers.

2reactions
ecs-jnguyencommented, Feb 24, 2021

@rmk135 Thanks for getting back to me. using the ‘string’ identifiers should help. Hopefully i don’t run into any circular dependencies lol

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dependency Injection using Decorators | by Chidume Nnamdi
These decorator functions (@Inject, @Injectable) uses the Reflect library to add metadata to classes or parameters. Reflect library is dedicated to adding and ......
Read more >
How to Use the @Injectable Decorator in Angular
The @Injectable decorator together with the 'providedIn' option means the service should not be added within the providers' array of a module.
Read more >
Configuring Dependency Injection in Angular - codecraft.tv
We use the @Injectable class decorators to automatically resolve and inject all the parameters of class constructor. We don't need to use the...
Read more >
Understanding dependency injection
The first step is to add the @Injectable decorator to show that the class can be injected. content_copy @Injectable() class HeroService {}. The...
Read more >
The @Injectable decorator and its relationship to ...
Let's look at the question: Which of the following statements regarding the @Injectable decorator are true? Answers: ... As you can see from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found