Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

[Enhancement] Allow calling methods and injecting their parameters #62

Open
cal-pratt opened this issue Aug 26, 2021 · 0 comments
Open

Comments

@cal-pratt
Copy link

Problem

A lot of times I just want to call a function which has arguments that need to be injected. In order to call the function like thisI basically have to create a wrapper class for the function which specifies the arguments required, and then call some method on the wrapper to pass in the injected arguments. This works but is a lot of boilerplate. e.g.

def foobar(foo: Foo) -> int:
    ...
    
class FoobarWrapper:
    def __init__(foo: Foo) -> None:
        self.foo = foo
    def call(self): -> int:
        return foobar(self.foo)

obj_graph = new_object_graph()
print("foobar returns:", obj_graph.provide(FoobarWrapper).call())

Solution

I want to be able to call functions with arbitrary parameters and have pinject construct all of the necessary inputs for me.
It seems like the library is set up nicely to support this, however, it requires me to access private members of the ObjectGraph instance.

Proof of Concept

After browsing through the implementation, I've been able to achieve my goal with the following 3 line hack. I provide a helper method around it to keep things simple and type-safe.

from typing import TypeVar, Callable
from pinject.object_graph import ObjectGraph

T = TypeVar("T")


def inject_func(obj_graph: ObjectGraph, func: Callable[..., T]) -> T:
    context = obj_graph._injection_context_factory.new(func)
    args, kwargs = obj_graph._obj_provider.get_injection_pargs_kwargs(func, context, [], {})
    return func(*args, **kwargs)

And here's how you'd call it:

class Bar:
    def __init__(self) -> None:
        self.a = 1


class Foo:
    def __init__(self, bar: Bar) -> None:
        self.bar = bar


def foobar(foo: Foo) -> int:
    return foo.bar.a


obj_graph = new_object_graph()
print("foobar returns:", inject_func(obj_graph, foobar))
foobar returns: 1

Desired Implementation

What I'd like to see is something like this at the same level as ObjectGraph.provide. Maybe ObjectGraph.invoke

obj_graph = new_object_graph()
print("foobar returns:", obj_graph.invoke(foobar))
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant