python-injector / python-injector/injector
Issue with injecting Generic classes - broke in python 3.7
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 94
- PR merge metrics
- No merged PRs in 30d
Description
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 :)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with injector_test.py and reproduce test_inject_simple_generic_class on Python 3.7 or later. Trace the failure through injector/init.py, especially get_binding, create_binding, provider_for, and args_to_inject. Done means the generic-class injection test passes on the affected Python versions without breaking existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100