mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Add implementation, typing stubs, and tests
This commit is contained in:
		
							parent
							
								
									4cb268a352
								
							
						
					
					
						commit
						1a01d7466b
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -142,7 +142,7 @@ cdef class FactoryDelegate(Delegate):
 | 
				
			||||||
cdef class FactoryAggregate(Provider):
 | 
					cdef class FactoryAggregate(Provider):
 | 
				
			||||||
    cdef dict __factories
 | 
					    cdef dict __factories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cdef Factory __get_factory(self, str factory_name)
 | 
					    cdef Factory __get_factory(self, object factory_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Singleton providers
 | 
					# Singleton providers
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,18 +283,18 @@ class FactoryDelegate(Delegate):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FactoryAggregate(Provider[T]):
 | 
					class FactoryAggregate(Provider[T]):
 | 
				
			||||||
    def __init__(self, **factories: Factory[T]): ...
 | 
					    def __init__(self, dict_: Optional[_Dict[Any, Factory[T]]] = None, **factories: Factory[T]): ...
 | 
				
			||||||
    def __getattr__(self, factory_name: str) -> Factory[T]: ...
 | 
					    def __getattr__(self, factory_name: Any) -> Factory[T]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @overload
 | 
					    @overload
 | 
				
			||||||
    def __call__(self, factory_name: str, *args: Injection, **kwargs: Injection) -> T: ...
 | 
					    def __call__(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> T: ...
 | 
				
			||||||
    @overload
 | 
					    @overload
 | 
				
			||||||
    def __call__(self, factory_name: str, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
 | 
					    def __call__(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
 | 
				
			||||||
    def async_(self, factory_name: str, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
 | 
					    def async_(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def factories(self) -> _Dict[str, Factory[T]]: ...
 | 
					    def factories(self) -> _Dict[Any, Factory[T]]: ...
 | 
				
			||||||
    def set_factories(self, **factories: Factory[T]) -> FactoryAggregate[T]: ...
 | 
					    def set_factories(self, dict_: Optional[_Dict[Any, Factory[T]]] = None, **factories: Factory[T]) -> FactoryAggregate[T]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BaseSingleton(Provider[T]):
 | 
					class BaseSingleton(Provider[T]):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2486,10 +2486,10 @@ cdef class FactoryAggregate(Provider):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    __IS_DELEGATED__ = True
 | 
					    __IS_DELEGATED__ = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, **factories):
 | 
					    def __init__(self, factories_dict_=None, **factories_kwargs):
 | 
				
			||||||
        """Initialize provider."""
 | 
					        """Initialize provider."""
 | 
				
			||||||
        self.__factories = {}
 | 
					        self.__factories = {}
 | 
				
			||||||
        self.set_factories(**factories)
 | 
					        self.set_factories(factories_dict_, **factories_kwargs)
 | 
				
			||||||
        super(FactoryAggregate, self).__init__()
 | 
					        super(FactoryAggregate, self).__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __deepcopy__(self, memo):
 | 
					    def __deepcopy__(self, memo):
 | 
				
			||||||
| 
						 | 
					@ -2521,13 +2521,17 @@ cdef class FactoryAggregate(Provider):
 | 
				
			||||||
        """Return dictionary of factories, read-only."""
 | 
					        """Return dictionary of factories, read-only."""
 | 
				
			||||||
        return self.__factories
 | 
					        return self.__factories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_factories(self, **factories):
 | 
					    def set_factories(self, factories_dict_=None, **factories_kwargs):
 | 
				
			||||||
        """Set factories."""
 | 
					        """Set factories."""
 | 
				
			||||||
 | 
					        factories = {}
 | 
				
			||||||
 | 
					        factories.update(factories_kwargs)
 | 
				
			||||||
 | 
					        if factories_dict_:
 | 
				
			||||||
 | 
					            factories.update(factories_dict_)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for factory in factories.values():
 | 
					        for factory in factories.values():
 | 
				
			||||||
            if isinstance(factory, Factory) is False:
 | 
					            if isinstance(factory, Factory) is False:
 | 
				
			||||||
                raise Error(
 | 
					                raise Error(f'{self.__class__} can aggregate only instances of {Factory}, given - {factory}')
 | 
				
			||||||
                    '{0} can aggregate only instances of {1}, given - {2}'
 | 
					
 | 
				
			||||||
                    .format(self.__class__, Factory, factory))
 | 
					 | 
				
			||||||
        self.__factories = factories
 | 
					        self.__factories = factories
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2561,12 +2565,10 @@ cdef class FactoryAggregate(Provider):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.__get_factory(factory_name)(*args, **kwargs)
 | 
					        return self.__get_factory(factory_name)(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cdef Factory __get_factory(self, str factory_name):
 | 
					    cdef Factory __get_factory(self, object factory_key):
 | 
				
			||||||
        if factory_name not in self.__factories:
 | 
					        if factory_key not in self.__factories:
 | 
				
			||||||
            raise NoSuchProviderError(
 | 
					            raise NoSuchProviderError(f'{self} does not contain factory with name {factory_key}')
 | 
				
			||||||
                '{0} does not contain factory with name {1}'.format(
 | 
					        return <Factory> self.__factories[factory_key]
 | 
				
			||||||
                    self, factory_name))
 | 
					 | 
				
			||||||
        return <Factory> self.__factories[factory_name]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef class BaseSingleton(Provider):
 | 
					cdef class BaseSingleton(Provider):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,19 @@ factory_a_9: providers.Factory[str] = provider9.a
 | 
				
			||||||
factory_b_9: providers.Factory[str] = provider9.b
 | 
					factory_b_9: providers.Factory[str] = provider9.b
 | 
				
			||||||
val9: str = provider9('a')
 | 
					val9: str = provider9('a')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					provider9_set_non_string_keys: providers.FactoryAggregate[str] = providers.FactoryAggregate()
 | 
				
			||||||
 | 
					provider9_set_non_string_keys.set_factories({Cat: providers.Factory(str, "str")})
 | 
				
			||||||
 | 
					factory_set_non_string_9: providers.Factory[str] = provider9_set_non_string_keys.factories[Cat]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					provider9_new_non_string_keys: providers.FactoryAggregate[str] = providers.FactoryAggregate(
 | 
				
			||||||
 | 
					    {Cat: providers.Factory(str, "str")},
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					factory_new_non_string_9: providers.Factory[str] = provider9_new_non_string_keys.factories[Cat]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					provider9_no_explicit_typing = providers.FactoryAggregate(a=providers.Factory(str, "str"))
 | 
				
			||||||
 | 
					provider9_no_explicit_typing_factory: providers.Factory[str] = provider9_no_explicit_typing.factories["a"]
 | 
				
			||||||
 | 
					provider9_no_explicit_typing_object: str = provider9_no_explicit_typing("a")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Test 10: to check the explicit typing
 | 
					# Test 10: to check the explicit typing
 | 
				
			||||||
factory10: providers.Provider[Animal] = providers.Factory(Cat)
 | 
					factory10: providers.Provider[Animal] = providers.Factory(Cat)
 | 
				
			||||||
animal10: Animal = factory10()
 | 
					animal10: Animal = factory10()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -498,7 +498,8 @@ class FactoryAggregateTests(unittest.TestCase):
 | 
				
			||||||
        self.example_b_factory = providers.Factory(self.ExampleB)
 | 
					        self.example_b_factory = providers.Factory(self.ExampleB)
 | 
				
			||||||
        self.factory_aggregate = providers.FactoryAggregate(
 | 
					        self.factory_aggregate = providers.FactoryAggregate(
 | 
				
			||||||
            example_a=self.example_a_factory,
 | 
					            example_a=self.example_a_factory,
 | 
				
			||||||
            example_b=self.example_b_factory)
 | 
					            example_b=self.example_b_factory,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_is_provider(self):
 | 
					    def test_is_provider(self):
 | 
				
			||||||
        self.assertTrue(providers.is_provider(self.factory_aggregate))
 | 
					        self.assertTrue(providers.is_provider(self.factory_aggregate))
 | 
				
			||||||
| 
						 | 
					@ -506,6 +507,35 @@ class FactoryAggregateTests(unittest.TestCase):
 | 
				
			||||||
    def test_is_delegated_provider(self):
 | 
					    def test_is_delegated_provider(self):
 | 
				
			||||||
        self.assertTrue(providers.is_delegated(self.factory_aggregate))
 | 
					        self.assertTrue(providers.is_delegated(self.factory_aggregate))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_init_with_non_string_keys(self):
 | 
				
			||||||
 | 
					        factory = providers.FactoryAggregate({
 | 
				
			||||||
 | 
					            self.ExampleA: self.example_a_factory,
 | 
				
			||||||
 | 
					            self.ExampleB: self.example_b_factory,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        object_a = factory(self.ExampleA, 1, 2, init_arg3=3, init_arg4=4)
 | 
				
			||||||
 | 
					        object_b = factory(self.ExampleB, 11, 22, init_arg3=33, init_arg4=44)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(object_a, self.ExampleA)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg1, 1)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg2, 2)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg3, 3)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg4, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(object_b, self.ExampleB)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg1, 11)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg2, 22)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg3, 33)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg4, 44)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            factory.factories,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                self.ExampleA: self.example_a_factory,
 | 
				
			||||||
 | 
					                self.ExampleB: self.example_b_factory,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_init_with_not_a_factory(self):
 | 
					    def test_init_with_not_a_factory(self):
 | 
				
			||||||
        with self.assertRaises(errors.Error):
 | 
					        with self.assertRaises(errors.Error):
 | 
				
			||||||
            providers.FactoryAggregate(
 | 
					            providers.FactoryAggregate(
 | 
				
			||||||
| 
						 | 
					@ -528,7 +558,37 @@ class FactoryAggregateTests(unittest.TestCase):
 | 
				
			||||||
        self.assertIsInstance(provider('example_a'), self.ExampleA)
 | 
					        self.assertIsInstance(provider('example_a'), self.ExampleA)
 | 
				
			||||||
        self.assertIsInstance(provider('example_b'), self.ExampleB)
 | 
					        self.assertIsInstance(provider('example_b'), self.ExampleB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_provides_returns_self(self):
 | 
					    def test_set_factories_with_non_string_keys(self):
 | 
				
			||||||
 | 
					        factory = providers.FactoryAggregate()
 | 
				
			||||||
 | 
					        factory.set_factories({
 | 
				
			||||||
 | 
					            self.ExampleA: self.example_a_factory,
 | 
				
			||||||
 | 
					            self.ExampleB: self.example_b_factory,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        object_a = factory(self.ExampleA, 1, 2, init_arg3=3, init_arg4=4)
 | 
				
			||||||
 | 
					        object_b = factory(self.ExampleB, 11, 22, init_arg3=33, init_arg4=44)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(object_a, self.ExampleA)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg1, 1)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg2, 2)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg3, 3)
 | 
				
			||||||
 | 
					        self.assertEqual(object_a.init_arg4, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(object_b, self.ExampleB)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg1, 11)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg2, 22)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg3, 33)
 | 
				
			||||||
 | 
					        self.assertEqual(object_b.init_arg4, 44)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            factory.factories,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                self.ExampleA: self.example_a_factory,
 | 
				
			||||||
 | 
					                self.ExampleB: self.example_b_factory,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_set_factories_returns_self(self):
 | 
				
			||||||
        provider = providers.FactoryAggregate()
 | 
					        provider = providers.FactoryAggregate()
 | 
				
			||||||
        self.assertIs(provider.set_factories(example_a=self.example_a_factory), provider)
 | 
					        self.assertIs(provider.set_factories(example_a=self.example_a_factory), provider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user