python-injector / python-injector/injector

Bind a provider to multiple interfaces?

Open
#205 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.5k
Forks
94
PR merge metrics
No merged PRs in 30d

Description

Hello Alec & open source contributors - I love this library - it feels very well designed and strikes a sweet spot between complexity / ease of use. However, I am running into a little bit of a snag and was wondering if anyone else came across this problem:

I currently have some helper provider modules that specify how to provide for a certain interface type (this is defined as a class member on modules that I wanted to bind DI to):

class _ModuleProvider(Module):
    @singleton
    @provider
    def provide_base(self, context : Context, config: Configuration) -> BaseType:
        return DerivedType(context, **config)

I dynamically load all modules and then add these to the provider container:

provider_containers = [config_provider]

# register all providers
for component in component_classes:
    # all modules should implement this provider class
    assert hasattr(
        component, "_ModuleProvider"
    ), "Component {} does not define a provider".format(component.__name__)
    provider_containers.append(component._ModuleProvider())

# later on
injector = Injector(provider_containers, auto_bind=False) # note I disabled autobind here
pipeline = injector.get(Pipeline)

However, some Pipeline implementations might have stricter requirements on the interface type so their constructor might take a DerivedType directly.

I currently work around this by declaring another provider

class _ModuleProvider(Module):
    @singleton
    @provider
    def provide_base(self, context : Context, config: Configuration) -> BaseType:
        return DerivedType(context, **config)

    @singleton
    @provider
    def provide_derived(self, context : Context, config: Configuration) -> DerivedType:
        return DerivedType(context, **config)

But I was just wondering if it's possible to do this:

class _ModuleProvider(Module):
    @singleton
    @provider
    def provide_derived(self, context : Context, config: Configuration) -> Union[BaseType, DerivedType]:
        return DerivedType(context, **config)

If there's a better way than what I was doing, I'd appreciate it too. Thank you!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provider methods and the Injector(provider_containers, auto_bind=False) entry point shown in the issue. Determine whether one provider can satisfy both BaseType and DerivedType, or whether the existing two-provider workaround is required; document the supported behavior and recommended pattern.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.