Skip to content

Issue with injecting Generic classes - broke in python 3.7 #175

@davebirch

Description

@davebirch

Hi there, currently upgrading a project using injector to python 3.8. We use MyPy generics in our project and I discovered that I can no longer inject my generic class.

On further investigation, this seems to be still present in master, works in python 3.6.8, then is broken in anything 3.7 and above.

The following unit test reproduces the issue:

GenericType = TypeVar("GenericType")


def test_inject_generic_class() -> None:

    class GenericClass(Generic[GenericType]):
        pass

    class InjectsGeneric:
        @inject
        def __init__(self, injected_generic: GenericClass[str]):
            self.injected_generic = injected_generic

    def bindings(binder: Binder) -> None:
        binder.bind(GenericClass)

    injector = Injector(bindings)
    instance = injector.get(InjectsGeneric)

    assert isinstance(instance, InjectsGeneric)
    assert isinstance(instance.injected_generic, GenericClass)

Output on the failing python versions is:

______________________ test_inject_simple_generic_class _______________________
Traceback (most recent call last):
  File "D:\git\injector\injector\__init__.py", line 658, in get_binding
    return self._get_binding(interface, only_this_binder=is_scope)
  File "D:\git\injector\injector\__init__.py", line 653, in _get_binding
    raise KeyError
KeyError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\git\injector\injector_test.py", line 1494, in test_inject_simple_generic_class
    instance = injector.get(InjectsGeneric)
  File "D:\git\injector\injector\__init__.py", line 963, in get
    result = scope_instance.get(interface, binding.provider).get(self)
  File "D:\git\injector\injector\__init__.py", line 291, in get
    return injector.create_object(self._cls)
  File "D:\git\injector\injector\__init__.py", line 990, in create_object
    self.call_with_injection(cls.__init__, self_=instance, kwargs=additional_kwargs)
  File "D:\git\injector\injector\__init__.py", line 1021, in call_with_injection
    dependencies = self.args_to_inject(
  File "D:\git\injector\injector\__init__.py", line 111, in wrapper
    return function(*args, **kwargs)
  File "D:\git\injector\injector\__init__.py", line 1069, in args_to_inject
    instance = self.get(interface)  # type: Any
  File "D:\git\injector\injector\__init__.py", line 952, in get
    binding, binder = self.binder.get_binding(interface)
  File "D:\git\injector\injector\__init__.py", line 667, in get_binding
    binding = self.create_binding(interface)
  File "D:\git\injector\injector\__init__.py", line 582, in create_binding
    provider = self.provider_for(interface, to)
  File "D:\git\injector\injector\__init__.py", line 644, in provider_for
    raise UnknownProvider('couldn\'t determine provider for %r to %r' % (interface, to))
injector.UnknownProvider: couldn't determine provider for injector_test.test_inject_simple_generic_class.<locals>.GenericClass[str] to None

Could do with getting this one fixed soon-ish, and will be taking a look tomorrow to see if I can create a PR that fixes it. If you have any hints or tips that might help, it would be appreciated :)

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