python-injector / python-injector/injector
@noninjectable seems to not work with dataclasses and auto_bind
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 94
- PR merge metrics
- No merged PRs in 30d
Description
The interaction between @dataclass, @noninjectable, and auto_bind=True seems to be broken. I would not expect the following to work, because foo shouldn't be injected due to the decorator,
from dataclasses import dataclass
from injector import Injector, inject
class Persistence:
pass
@inject
@noninjectable('foo')
@dataclass
class Parent:
p: Persistence
foo: int
injector = Injector()
parent = injector.get(Parent)
print(type(parent))
print(parent.foo)
but it actually runs and produces
<class '__main__.Parent'>
0
The same implementation without @dataclass
from injector import Injector, inject
class Persistence:
pass
class Parent:
@inject
@noninjectable('foo')
def __init__(self, persistence: Persistence, foo: int):
self.p = persistence
self.foo = foo
injector = Injector()
parent = injector.get(Parent)
print(type(parent))
print(parent.foo)
throws an exception, as expected
Traceback (most recent call last):
File "examples\injector_test.py", line 116, in <module>
parent = injector.get(Parent)
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 963, in get
result = scope_instance.get(interface, binding.provider).get(self)
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 291, in get
return injector.create_object(self._cls)
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 990, in create_object
self.call_with_injection(cls.__init__, self_=instance, kwargs=additional_kwargs)
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 1032, in call_with_injection
reraise(e, CallError(self_, callable, args, dependencies, e, self._stack))
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 211, in reraise
raise exception.with_traceback(tb)
File "[USER_DIR]\AppData\Local\pypoetry\Cache\virtualenvs\[VENV]\lib\site-packages\injector\__init__.py", line 1030, in call_with_injection
return callable(*full_args, **dependencies)
injector.CallError: Call to Parent.__init__(persistence=<__main__.Persistence object at 0x0000023D47334940>) failed: __init__() missing 1 required positional argument: 'foo' (injection stack: [])
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 by running the dataclass reproduction and compare its path through Injector.get, create_object, and call_with_injection with the non-dataclass example. Check how Parent.init is inspected when @dataclass generates it and how @noninjectable('foo') is applied. Done means foo is not injected and the dataclass case behaves consistently with the explicit constructor case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100