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 service with arguments #1

Closed
mehmetgiritli opened this issue Nov 13, 2024 · 7 comments
Closed

Inject service with arguments #1

mehmetgiritli opened this issue Nov 13, 2024 · 7 comments

Comments

@mehmetgiritli
Copy link

I was wondering if it there is a way to inject a service which requires an argument to be provided in it's init?

I am aware of the parameters option in container config, and the possibility to pass those with Inject.

I am trying to pass an object from the code into a service basically, at injection time.

@maldoinc
Copy link
Owner

What you're describing should be doable via a factory. https://maldoinc.github.io/wireup/0.12.0/factory_functions/

You can request all dependencies you need in the factory and pass them down alongside your other thing you want to inject.

@service
def example_factory(container_deps_go_here) -> ExampleService:
    return ExampleService(container_deps, your_other_dependency)

Additionally if the object you're describing is also a service that was created somewhere else you can register that as a service directly and have it be injected as usual.

@service
def object_factory() -> OtherDependency:
   return fetch_object_from_somewhere

@service
class ExampleService:
    def __init__(self, other: OtherDependency) -> None:
        ...

Let me know if this helped otherwise feel free to add a bit more specific info.

@mehmetgiritli
Copy link
Author

mehmetgiritli commented Nov 14, 2024

Thank you for your help with the examples. Here is what I'm trying to achieve:

Using FastAPI, I'm trying to inject a service and pass the Request object from FastAPI into it.

I think the Request aspect of it makes things a little more complicated, because it is not a dependency managed by wireup.

Here is an example of my failed attempt, while trying factory solution.

Inject the top level Keycloak service at the endpoint:

@app.get("/login")
def getLogin(keycloak: Annotated[Keycloak, Inject()]):
    return keycloak.login()

Keycloak service depends on Session service:

@service(lifetime=ServiceLifetime.TRANSIENT)
class Keycloak:
    def __init__(self, session: Session):

And Session service needs Request:

from fastapi import Request
...

@service(lifetime=ServiceLifetime.TRANSIENT)
class Session:
    def __init__(self, request: Request):

...

@service
def session_factory(request: Request) -> Session:
    return Session(request)

Of course it can't find the Request to inject.

Request is only available like this:

@app.get("/login")
def getLogin(request: Request, keycloak: Annotated[Keycloak, Inject()]):
    return keycloak.login()

But then I can not pass it to Keycloak's constructor.

@mehmetgiritli
Copy link
Author

Probably need to wait for maldoinc/wireup#25 ?

@maldoinc
Copy link
Owner

maldoinc commented Nov 14, 2024

I'm guessing you need your session to access request data? In any case I set up a quick PR that adds Request as a wireup dependency when using it with the fastapi integration.

Do check it out and let me know if you encounter any issues.

maldoinc/wireup#38

You can install it with the following command pip install git+https://github.com/maldoinc/wireup.git@fastapi-request-service. If it works as expected, I'll merge it because I do think it makes sense to have it even though I think it should be used sparingly.

Also, if you also find the Annotated[Keycloak, Inject()] syntax a bit ugly (which is sadly required in fastapi), you can create an alias to improve it somewhat.

T = TypeVar("T")
Autowired = Annotated[T, Inject()]

then you can use as Autowired[Keycloak] instead.

@iverberk
Copy link

Well, what a coincidence. I needed the request object in my authentication service (to grab the JWT token) and this seems to work just fine. Looking forward to this being merged!

@mehmetgiritli
Copy link
Author

@maldoinc Many thanks for this, I can confirm the functionality works as expected. Much appreciated.

@maldoinc
Copy link
Owner

Thanks for the feedback! This is now released on 0.13.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants