def test_create_provider_from_named_binding(self): class MyOtherType: def __init__(self, arg: str): self.arg = arg mock_provider_1 = create_autospec(Provider) mock_provider_1.get.return_value = "my_arg_1" self.state.provider_creator.get_provider.side_effect = [ NoBindingFound, mock_provider_1, self.mock_scope_provider, ] provider = self.adapter.create( RegisteredBinding(SelfBinding(MyOtherType, named="my_name")), self.context) instance = provider.get() self.assertIsInstance(instance, MyOtherType) self.assertEqual("my_arg_1", instance.arg) self.assertEqual([ call(self.context.get_child_context(Target(str, "arg"))), call(self.context.get_child_context(Target(str))), call(self.context.get_child_context(Target(SingletonScope))), ], self.state.provider_creator.get_provider.call_args_list)
def test_create_provider_with_named_args(self): class MyOtherType: @named_arg("arg", "my_name") def __init__(self, *arg: str): self.arg = arg mock_provider_1 = create_autospec(Provider) mock_provider_1.get.return_value = ["my_arg_1"] self.state.provider_creator.get_provider.side_effect = [ mock_provider_1, self.mock_scope_provider, ] provider = self.adapter.create( RegisteredBinding(SelfBinding(MyOtherType)), self.context) instance = provider.get() self.assertIsInstance(instance, MyOtherType) self.assertEqual(("my_arg_1", ), instance.arg) self.assertEqual([ call( self.context.get_child_context(Target(List[str], "my_name"), allow_jit_provider=True)), call( self.context.get_child_context(Target(SingletonScope), allow_jit_provider=True)), ], self.state.provider_creator.get_provider.call_args_list)
def test_accept(self): self.binding_registry.__contains__.side_effect = [ True, False, ] self.assertTrue(self.provider_factory.accept(self.str_context)) self.assertFalse(self.provider_factory.accept(self.int_context)) self.assertEqual([ call(Target(str)), call(Target(int)), ], self.binding_registry.__contains__.call_args_list)
def test_register_class_binding_creates_self_binding_if_target_does_not_exist( self): class MySubType(MyType): pass class_binding = RegisteredBinding(ClassBinding(MyType, MySubType)) self.binding_registry.register(class_binding) self.assertIs(class_binding, self.binding_registry.get_binding(Target(MyType))) self_binding = self.binding_registry.get_binding(Target(MySubType)) self.assertIsInstance(self_binding.raw_binding, SelfBinding) self.assertEqual(MySubType, self_binding.raw_binding.target_type)
def setUp(self): self.binding_registry = create_autospec(BindingRegistry, spec_set=True) self.provider_factory = FromBindingProviderFactory() self.provider_creator = create_autospec(ProviderCreator, spec_set=True) self.mock_scope_provider = create_autospec(Provider, spec_set=True) self.scope = PerLookupScope() self.mock_scope_provider.get.return_value = self.scope self.state = InjectionState( self.provider_creator, self.binding_registry, ) self.context = InjectionContext(Target(MyType), self.state) self.str_context = InjectionContext(Target(str), self.state) self.int_context = InjectionContext(Target(int), self.state)
def test_create_provider_with_parameters(self): class MyOtherType: def __init__(self, arg_1: str, arg_2: int, *args: float, arg_3: bool, **kwargs): self.args = [arg_1, arg_2, *args] self.kwargs = { "arg_3": arg_3, **kwargs, } mock_provider_1 = create_autospec(Provider) mock_provider_1.get.return_value = "my_arg_1" mock_provider_2 = create_autospec(Provider) mock_provider_2.get.return_value = 2 mock_provider_3 = create_autospec(Provider) mock_provider_3.get.return_value = [1.2, 3.4] mock_provider_4 = create_autospec(Provider) mock_provider_4.get.return_value = True self.state.provider_creator.get_provider.side_effect = [ mock_provider_1, mock_provider_2, mock_provider_3, mock_provider_4, self.mock_scope_provider, ] provider = self.adapter.create( RegisteredBinding(SelfBinding(MyOtherType)), self.context) instance = provider.get() self.assertIsInstance(instance, MyOtherType) self.assertEqual(["my_arg_1", 2, 1.2, 3.4], instance.args) self.assertEqual({"arg_3": True}, instance.kwargs) self.assertEqual([ call( self.context.get_child_context(Target(str, "arg_1"), allow_jit_provider=False)), call( self.context.get_child_context(Target(int, "arg_2"), allow_jit_provider=False)), call( self.context.get_child_context(Target(List[float], "args"), allow_jit_provider=False)), call( self.context.get_child_context(Target(bool, "arg_3"), allow_jit_provider=False)), call( self.context.get_child_context(Target(SingletonScope), allow_jit_provider=True)), ], self.state.provider_creator.get_provider.call_args_list)
def test_create_provider_from_provider_class_binding(self): self.state.provider_creator.get_provider.side_effect = [ self.provider_provider, self.mock_scope_provider, ] provider = self.adapter.create(RegisteredBinding(ProviderBinding(MyType, Provider)), self.context) instance = provider.get() self.assertIs(instance, self.instance) self.assertEqual([ call(self.context.get_child_context(Target(Provider))), call(self.context.get_child_context(Target(SingletonScope))), ], self.state.provider_creator.get_provider.call_args_list)
def test_create_with_parent_binding(self): self.state.parent_state = InjectionState( create_autospec(ProviderCreator, spec_set=True), self.binding_registry) self.binding_registry.__contains__.side_effect = [ False, True, ] self.assertTrue(self.provider_factory.accept(self.str_context)) self.assertEqual([ call(Target(str)), call(Target(str)), ], self.binding_registry.__contains__.call_args_list)
def test_register_class_binding_does_not_create_self_binding_if_target_exists( self): class MySubType(MyType): pass my_instance = MySubType() class_binding = RegisteredBinding(ClassBinding(MyType, MySubType)) instance_binding = RegisteredBinding( InstanceBinding(MySubType, my_instance)) self.binding_registry.register(instance_binding) self.binding_registry.register(class_binding) self.assertIs(class_binding, self.binding_registry.get_binding(Target(MyType))) self.assertIs(instance_binding, self.binding_registry.get_binding(Target(MySubType)))
def test_get_binding_returns_named_binding(self): self.binding_registry.register(self.my_type_binding) self.binding_registry.register(self.my_type_named_binding) self.binding_registry.register(self.my_type_binding_2) binding = self.binding_registry.get_binding(Target(MyType, "my_name")) self.assertEqual(self.my_type_named_binding, binding)
def test_register_multi_binding_saves_binding_to_known_type_in_order(self): item_binding_1 = ItemBinding(MyType) registered_item_binding_1 = RegisteredBinding(SelfBinding(MyType)) item_binding_2 = ItemBinding(bound_instance=MyType()) registered_item_binding_2 = RegisteredBinding( InstanceBinding(MyType, item_binding_2.bound_instance)) binding_1 = RegisteredMultiBinding(MultiBinding( MyType, [item_binding_1]), item_bindings=[ registered_item_binding_1, ]) binding_2 = RegisteredMultiBinding(MultiBinding( MyType, [item_binding_2], override_bindings=False), item_bindings=[ registered_item_binding_2, ]) self.binding_registry.register(binding_1) self.binding_registry.register(binding_2) registered_binding = self.binding_registry.get_binding( Target(List[MyType])) self.assertIsInstance(registered_binding, RegisteredMultiBinding) self.assertIsInstance(registered_binding.raw_binding, MultiBinding) self.assertEqual( [registered_item_binding_1, registered_item_binding_2], registered_binding.item_bindings)
def create( self, context: InjectionContext[Optional[InjectedT]] ) -> Provider[InjectedT]: new_target = Target(context.target.type.__args__[0], context.target.named) new_context = context.get_child_context(new_target) return new_context.get_provider()
def create( self, context: InjectionContext[Tuple[InjectedT]] ) -> Provider[Tuple[InjectedT]]: new_target = Target(List[context.target.type.__args__[0]], context.target.named) new_context = context.get_child_context(new_target) return FromClassProvider(tuple, [new_context.get_provider()], None, {})
def test_list_binding_with_named_arguments(self): self.binding_registry.register( RegisteredMultiBinding( MultiBinding( MyType, [ ItemBinding(bound_instance=self.named_instance), ], named="my_name", ), item_bindings=[ RegisteredBinding(InstanceBinding(MyType, self.named_instance, named="my_name")) ] ) ) self.binding_registry.register( RegisteredMultiBinding( MultiBinding( MyType, [ ItemBinding(bound_instance=self.my_instance), ], ), item_bindings=[ RegisteredBinding(InstanceBinding(MyType, self.my_instance)) ] ) ) self.binding_registry.register(RegisteredBinding(self.my_named_instance_binding)) self.binding_registry.register(RegisteredBinding(SelfBinding(MyType))) context = InjectionContext(Target(List[MyType], "my_name"), self.state) provider = self.provider_creator.get_provider(context) list_instance = provider.get() self.assertEqual([self.named_instance], list_instance)
def setUp(self) -> None: self.binding_registry = BindingRegistry() self.binding_registry.register(RegisteredBinding(InstanceBinding(SingletonScope, SingletonScope()))) self.provider_creator = ProviderCreator() self.state = InjectionState( self.provider_creator, self.binding_registry, ) self.context = InjectionContext(Target(MyType), self.state) self.other_context = InjectionContext(Target(MyOtherType), self.state) self.named_context = InjectionContext(Target(MyType, "my_name"), self.state) self.my_instance = MyType() self.my_instance_binding = InstanceBinding(MyType, self.my_instance) self.named_instance = MyType() self.my_named_instance_binding = InstanceBinding(MyType, self.named_instance, named="my_name") self.my_other_instance = MyOtherType() self.my_other_instance_binding = InstanceBinding(MyOtherType, self.my_other_instance)
def test_optional_binding(self): self.binding_registry.register(RegisteredBinding(self.my_instance_binding)) context = InjectionContext(Target(Optional[MyType]), self.state) provider = self.provider_creator.get_provider(context) self.assertIsInstance(provider, FromInstanceProvider) instance = provider.get() self.assertIs(self.my_instance, instance)
def test_get_named_binding_from_string(self): self.binding_registry.register(self.my_type_binding) self.binding_registry.register(self.my_type_named_binding) self.binding_registry.register(self.other_type_binding) binding = self.binding_registry.get_binding(Target( "MyType", "my_name")) self.assertEqual(self.my_type_named_binding, binding)
def test_list_implicit_binding(self): instance = MyType() self.binding_registry.register(RegisteredBinding(InstanceBinding(MyType, instance))) context = InjectionContext(Target(List[MyType]), self.state) provider = self.provider_creator.get_provider(context) self.assertIsInstance(provider, ListProvider) list_instance = provider.get() self.assertEqual([instance], list_instance)
def test_register_provider_binding_with_class_creates_self_binding(self): class MyProvider(Provider[str]): def get(self) -> str: return "hello" provider_binding = RegisteredBinding( ProviderBinding(str, MyProvider, PerLookupScope, "my_name")) self.binding_registry.register(provider_binding) self.assertEqual( provider_binding, self.binding_registry.get_binding(Target(str, "my_name"))) provider_binding = self.binding_registry.get_binding( Target(MyProvider, "my_name")) self.assertIsInstance(provider_binding.raw_binding, SelfBinding) self.assertEqual(MyProvider, provider_binding.raw_binding.target_type) self.assertEqual(PerLookupScope, provider_binding.raw_binding.scope)
def test_create_named_provider(self): self.state.provider_creator.get_provider.side_effect = [ self.provider_provider, self.mock_scope_provider, ] context = InjectionContext(Target(MyType, "my_name"), self.state) provider = self.adapter.create( RegisteredBinding(ProviderBinding(MyType, Provider, named="my_name")), context, ) instance = provider.get() self.assertIs(instance, self.instance) self.assertEqual([ call(context.get_child_context(Target(Provider, "my_name"))), call(context.get_child_context(Target(SingletonScope))), ], self.state.provider_creator.get_provider.call_args_list)
def create(self, context: InjectionContext[Optional[InjectedT]]) -> Provider[InjectedT]: for subtype in context.target.type.__args__: try: new_target = Target(subtype, context.target.named) new_context = context.get_child_context(new_target) return new_context.get_provider() except NoBindingFound: pass raise NoBindingFound(f"No binding found for {context.target}")
def create(self, binding: RegisteredBinding[ProviderBinding[InjectedT]], context: InjectionContext[InjectedT]) -> Provider[InjectedT]: if isinstance(binding.raw_binding.bound_provider, Provider): return binding.raw_binding.bound_provider provider_target = Target(binding.raw_binding.bound_provider, binding.raw_binding.named) provider_context = context.get_child_context(provider_target) provider_provider = provider_context.get_provider() unscoped_provider = FromProviderProvider( provider_provider, ) scope_context = context.get_child_context(Target(binding.raw_binding.scope)) try: scope_provider = scope_context.get_provider() except NoBindingFound: raise NonInjectableTypeError(f"Could not create a provider for {binding}: they are no bindings for" f"the scope {binding.raw_binding.scope}") return scope_provider.get().get_scoped_provider(unscoped_provider)
def setUp(self): self.adapter = SelfBindingToProviderAdapter() self.state = InjectionState( create_autospec(ProviderCreator, spec_set=True), create_autospec(BindingRegistry, spec_set=True), ) self.context = InjectionContext(Target(MyType), self.state) self.mock_scope_provider = create_autospec(Provider, spec_set=True) self.scope = PerLookupScope() self.mock_scope_provider.get.return_value = self.scope
def _get_positional_parameter_provider(self, parameter: Parameter, current_class: Type, context: InjectionContext[InjectedT]) -> Provider[List[InjectedT]]: if parameter.annotation is Parameter.empty: return FromInstanceProvider([]) if TypeChecker.is_named(parameter.annotation): provider = self._get_provider([ Target(List[parameter.annotation.original_type], parameter.annotation.name, default=[]) ], context) else: provider = self._get_provider([ Target(List[parameter.annotation], parameter.name, default=[]), Target(List[parameter.annotation], default=[]), ], context) if provider: return provider self.logger.debug(f"Could not find a binding for *{parameter.name}: {parameter.annotation} required by " f"{current_class}, will inject nothing") return FromInstanceProvider([])
def _get_parameter_provider(self, parameter: Parameter, current_class: Type, context: InjectionContext[InjectedT]) -> Provider[InjectedT]: default_value = parameter.default if parameter.default is not Parameter.empty else EMPTY if parameter.annotation is not Parameter.empty: if TypeChecker.is_named(parameter.annotation): provider = self._get_provider([ Target(parameter.annotation.original_type, parameter.annotation.name, default_value)], context) else: provider = self._get_provider([ Target(parameter.annotation, parameter.name, default_value), Target(parameter.annotation, None, default_value), ], context) if provider: return provider if parameter.default is not Parameter.empty: return FromInstanceProvider(parameter.default) raise NonInjectableTypeError(f"Could not find a binding or a default value for {parameter.name}: " f"{get_class_full_name(parameter.annotation)} required by {current_class}")
def test_create_provider_without_args(self): self.state.provider_creator.get_provider.return_value = self.mock_scope_provider provider = self.adapter.create(RegisteredBinding(SelfBinding(MyType)), self.context) self.state.provider_creator.get_provider.assert_called_once_with( self.context.get_child_context(Target(SingletonScope)), ) self.assertIsInstance(provider, FromClassProvider) instance = provider.get() self.assertIsInstance(instance, MyType)
def test_missing_binding_raises_exception(self): class MyParentClass: def __init__(self, my_param: MyType): self.my_param = my_param my_parent_binding = SelfBinding(MyParentClass) context = InjectionContext(Target(MyParentClass), self.state) self.binding_registry.register(RegisteredBinding(my_parent_binding)) with self.assertRaises(NonInjectableTypeError): self.provider_creator.get_provider(context)
def test_create_scoped_provider(self): self.state.provider_creator.get_provider.side_effect = [ self.provider_provider, FromInstanceProvider(ThreadScope()), ] provider = self.adapter.create( RegisteredBinding(ProviderBinding(MyType, Provider, scope=ThreadScope)), self.context, ) instance = provider.get() self.assertIs(instance, self.instance) self.assertEqual( [ call(self.context.get_child_context(Target(Provider))), call(self.context.get_child_context(Target(ThreadScope))), ], self.state.provider_creator.get_provider.call_args_list, ) self.assertIsInstance(provider, ThreadScopedProvider)
def test_type_binding_with_explicit_binding(self): class SubType(MyType): pass self.binding_registry.register(RegisteredBinding(InstanceBinding(Type[MyType], MyType))) self.binding_registry.register(RegisteredBinding(ClassBinding(MyType, SubType))) context = InjectionContext(Target(Type[MyType]), self.state) provider = self.provider_creator.get_provider(context) self.assertIsInstance(provider, FromInstanceProvider) instance = provider.get() self.assertIs(MyType, instance)
def test_type_binding_without_class_binding(self): class MyParentClass: def __init__(self, my_param: Type[MyType]): self.my_param = my_param parent_binding = SelfBinding(MyParentClass) self.binding_registry.register(RegisteredBinding(self.my_instance_binding)) self.binding_registry.register(RegisteredBinding(parent_binding)) context = InjectionContext(Target(Type[MyType]), self.state) with self.assertRaises(NonInjectableTypeError): self.provider_creator.get_provider(context)