Skip to content

How to implement a plug-in system with multibind? #121

@eirikur-grid

Description

@eirikur-grid

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

binder.multibind(List[Plugin], [GreenPlugin, RedPlugin])

then injector.get(List[Plugin]) just returns the list of classes, rather than a list of instantiated objects.

If I do this:

binder.multibind(List[Plugin], GreenPlugin)
binder.multibind(List[Plugin], RedPlugin)

then I get the following error when calling injector.get(List[Plugin])

>   return [i for provider in self._providers for i in provider.get(injector)]
E   TypeError: 'GreenPlugin' object is not iterable

I've been able to get this approach to work by having my base Plugin class pretend to be iterable like so:

class Plugin:
    # Dependency Injection hack for making multibind work
    def __getitem__(self, item):
        if item == 0:
            return self
        raise IndexError

but it's not very nice.

I could do this:

def configure(binder):
  binder.bind(GreenPlugin)
  binder.bind(RedPlugin)

@provider
def get_plugins(green: GreenPlugin, red: RedPlugin) -> List[Plugin]:
  return [green, red]

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions