diff --git a/CHANGES b/CHANGES index 18dbbcd..13c551b 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,9 @@ Injector Change Log :class:`~injector.Module` constructors or :meth:`injector.Module.configure` methods) - removed `extends` decorator - few classes got useful __repr__ implementations +- fixed injecting ProviderOf and AssistedBuilders when :class:`injector.Injector` + auto_bind is set to False (previously would result in `UnsatisfiedRequirement` + error) 0.9.1 ----- diff --git a/injector.py b/injector.py index 90fd488..bffdce1 100644 --- a/injector.py +++ b/injector.py @@ -452,12 +452,20 @@ class Binder(object): try: return self._get_binding(key) except (KeyError, UnsatisfiedRequirement): - if self._auto_bind: + # The special interface is added here so that requesting a special + # interface with auto_bind disabled works + if self._auto_bind or self._is_special_interface(key.interface): binding = self.create_binding(key.interface) self._bindings[key] = binding return binding raise UnsatisfiedRequirement(cls, key) + def _is_special_interface(self, interface): + # "Special" interfaces are ones that you cannot bind yourself but + # you can request them (for example you cannot bind ProviderOf(SomeClass) + # to anything but you can inject ProviderOf(SomeClass) just fine + return isinstance(interface, (ProviderOf, AssistedBuilder)) + class Scope(object): """A Scope looks up the Provider for a binding. diff --git a/injector_test.py b/injector_test.py index d20075f..1013001 100644 --- a/injector_test.py +++ b/injector_test.py @@ -1159,3 +1159,29 @@ def test_providerof_is_safe_to_use_with_multiple_injectors(): assert provider1.get() == 1 assert provider2.get() == 2 + + +def test_special_interfaces_work_with_auto_bind_disabled(): + class InjectMe(object): + pass + + def configure(binder): + binder.bind(InjectMe, to=InstanceProvider(InjectMe())) + + injector = Injector(configure, auto_bind=False) + + # This line used to fail with: + # Traceback (most recent call last): + # File "/projects/injector/injector_test.py", line 1171, + # in test_auto_bind_disabled_regressions + # injector.get(ProviderOf(InjectMe)) + # File "/projects/injector/injector.py", line 687, in get + # binding = self.binder.get_binding(None, key) + # File "/projects/injector/injector.py", line 459, in get_binding + # raise UnsatisfiedRequirement(cls, key) + # UnsatisfiedRequirement: unsatisfied requirement on + # + injector.get(ProviderOf(InjectMe)) + + # This used to fail with an error similar to the ProviderOf one + injector.get(AssistedBuilder(cls=InjectMe))