python-injector / python-injector/injector
Unable to bind Annotated to instances of origin
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 94
- PR merge metrics
- No merged PRs in 30d
Description
Originally stemming from interest in #133 , I too thought to replicate Guice's @Named convention. In doing so, I originally used the typing.NewType (prior to having even seen the aforementioned issue) and succeeded. However, instantiating a type for each simple alias, I thought typing.Annotated (albeit, using typing_extensions.Annotated) would be more idiomatic.
Given a simple example:
import pathlib
import injector
ConfigFile = injector.Annotated[pathlib.WindowsPath, 'config']
cfg_file = pathlib.Path.home() / 'settings.cfg'
class AppModule(injector.Module):
def configure(self, binder):
binder.bind(ConfigFile, to=cfg_file) # Guice uses annotatedWith here
class App:
@injector.inject
def __init__(self, cfg: ConfigFile):
self.config = cfg
app = injector.Injector(AppModule).get(App)
...throws...
Traceback (most recent call last):
File "E:\Programming\test\test_injector\test.py", line 20, in <module>
app = injector.Injector(AppModule).get(App)
File "C:\Python37\lib\site-packages\injector\__init__.py", line 913, in __init__
self.binder.install(module)
File "C:\Python37\lib\site-packages\injector\__init__.py", line 577, in install
instance(self)
File "C:\Python37\lib\site-packages\injector\__init__.py", line 860, in __call__
self.configure(binder)
File "E:\Programming\test\test_injector\test.py", line 12, in configure
binder.bind(ConfigFile, to=cfg_file) # Guice uses annotatedWith here
File "C:\Python37\lib\site-packages\injector\__init__.py", line 479, in bind
self._bindings[interface] = self.create_binding(interface, to, scope)
File "C:\Python37\lib\site-packages\injector\__init__.py", line 582, in create_binding
provider = self.provider_for(interface, to)
File "C:\Python37\lib\site-packages\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 typing_extensions.Annotated[pathlib.WindowsPath, 'config'] to WindowsPath('C:/Users/Paul/settings.cfg')
My belief is that provider_for does not adequately check to see if the interface is an _AnnotatedAlias or not. The origin variable resolves to the base interface correctly, in this case pathlib.WindowsPath, but since base_type is typing_extenstions.Annotated, not check is made given that case.
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 at the Binder.provider_for entry point shown in the traceback and reproduce the pathlib.WindowsPath example with typing_extensions.Annotated. Trace how the Annotated interface and its origin are handled; done means binding the annotated alias to cfg_file succeeds and injector.Injector(AppModule).get(App) constructs App with that value.
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
- 25/100