Open eirikur-grid opened 5 years ago
Being able to multibind to types was definitely the original intent, as you can see from the documentation. I'll take a look.
@alecthomas This is the relevant part of multibind
signature right now:
@overload
def multibind(
self,
interface: Type[List[T]],
to: Union[List[T], Callable[..., List[T]], Provider[List[T]]],
scope: Union[Type['Scope'], 'ScopeDecorator'] = None,
) -> None:
pass
I think extending it to be
@overload
def multibind(
self,
interface: Type[List[T]],
# Line below changed
to: Union[Callable[..., List[T]], Provider[List[T]], List[Union[T, Provider[T], Type[T], Callable[..., T]]]],
scope: Union[Type['Scope'], 'ScopeDecorator'] = None,
) -> None:
pass
or something similar and handling it would to the job.
@eirikur-grid You could also try
@provider
def get_plugins(injector: Injector) -> List[Plugin]:
return [injector.get(plugin_class) for plugin_class in [X, Y, Z]]
right now, which should be slightly less annoying.
On that regard, wouldn't it be sensible to support things from the collections
module and some typing
ones aswell?
Iterable
, Collection
, Counter
, Sequence
, ...
I have no reasonable idea how those would even work and fit the system so I can't really say.
jstasiak's solution worked for me, but got an error that I should use @multiprovirder
instead of @provider
:
@injector.multiprovider
def get_all_plugins(di: injector.Injector) -> Dict[str, PluginInterface]:
return {
"red": di.get(RedPlugin),
"green": di.get(GreenPlugin)
}
library version is 0.18.4
I've used Guice in the past for registering and instantiating plug-ins using the multibind extension. I found that straight-forward to do based on the Guice documentation. However, I'm struggling to do the same using python injector. All the tests and documentation I've found use
multibind
in conjunction with lists or dictionaries containing concrete values (strings or ints). I need the plug-ins to be instantiated by the DI framework.If I bind to a list of classes like this
then
injector.get(List[Plugin])
just returns the list of classes, rather than a list of instantiated objects.If I do this:
then I get the following error when calling
injector.get(List[Plugin])
I've been able to get this approach to work by having my base Plugin class pretend to be iterable like so:
but it's not very nice.
I could do this:
but that results in a lot of repetition. Adding a new plugin would mean binding it, adding it to the argument list of the provider function and the list it returns.
I feel like I must be missing something. How should a plug-in system be implemented using python injector?