mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Add validation of provided type for Factory provider
This commit is contained in:
		
							parent
							
								
									ee37558946
								
							
						
					
					
						commit
						10e76f65d7
					
				| 
						 | 
					@ -246,6 +246,16 @@ class Factory(Provider):
 | 
				
			||||||
        some_object = factory()
 | 
					        some_object = factory()
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    provided_type = None
 | 
				
			||||||
 | 
					    """Provided type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    If provided type is defined, :py:class:`Factory` checks that
 | 
				
			||||||
 | 
					    :py:attr:`Factory.provides` is subclass of
 | 
				
			||||||
 | 
					    :py:attr:`Factory.provided_type`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :type: type | None
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    __slots__ = ('provides', 'args', 'kwargs', 'attributes', 'methods')
 | 
					    __slots__ = ('provides', 'args', 'kwargs', 'attributes', 'methods')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, provides, *args, **kwargs):
 | 
					    def __init__(self, provides, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -261,10 +271,7 @@ class Factory(Provider):
 | 
				
			||||||
        :param kwargs: Dictionary of injections.
 | 
					        :param kwargs: Dictionary of injections.
 | 
				
			||||||
        :type kwargs: dict
 | 
					        :type kwargs: dict
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not callable(provides):
 | 
					        self.provides = self._ensure_provides_type(provides)
 | 
				
			||||||
            raise Error('Factory provider expects to get callable, ' +
 | 
					 | 
				
			||||||
                        'got {0} instead'.format(str(provides)))
 | 
					 | 
				
			||||||
        self.provides = provides
 | 
					 | 
				
			||||||
        """Class or other callable that provides object for creation.
 | 
					        """Class or other callable that provides object for creation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :type: type | callable
 | 
					        :type: type | callable
 | 
				
			||||||
| 
						 | 
					@ -328,6 +335,31 @@ class Factory(Provider):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return instance
 | 
					        return instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _ensure_provides_type(self, provides):
 | 
				
			||||||
 | 
					        """Check if provided type is valid type for this factory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param provides: Factory provided type
 | 
				
			||||||
 | 
					        :type provides: type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :raise: :py:exc:`dependency_injector.errors.Error` if ``provides``
 | 
				
			||||||
 | 
					                is not callable
 | 
				
			||||||
 | 
					        :raise: :py:exc:`dependency_injector.errors.Error` if ``provides``
 | 
				
			||||||
 | 
					                doesn't meet factory provided type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: validated ``provides``
 | 
				
			||||||
 | 
					        :rtype: type
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if not callable(provides):
 | 
				
			||||||
 | 
					            raise Error('Factory provider expects to get callable, ' +
 | 
				
			||||||
 | 
					                        'got {0} instead'.format(str(provides)))
 | 
				
			||||||
 | 
					        if (self.__class__.provided_type and
 | 
				
			||||||
 | 
					                not issubclass(provides, self.__class__.provided_type)):
 | 
				
			||||||
 | 
					            raise Error('{0} can provide only {1} instances'.format(
 | 
				
			||||||
 | 
					                '.'.join((self.__class__.__module__,
 | 
				
			||||||
 | 
					                          self.__class__.__name__)),
 | 
				
			||||||
 | 
					                self.__class__.provided_type))
 | 
				
			||||||
 | 
					        return provides
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        """Return string representation of provider.
 | 
					        """Return string representation of provider.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,8 @@ follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Development version
 | 
					Development version
 | 
				
			||||||
-------------------
 | 
					-------------------
 | 
				
			||||||
- No features.
 | 
					- Add possibility to validate ``Factory`` provided type on ``Factory`` 
 | 
				
			||||||
 | 
					  initialization.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.11.2
 | 
					1.11.2
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,6 +176,41 @@ class FactoryTests(unittest.TestCase):
 | 
				
			||||||
        """Test creation of provider with a callable."""
 | 
					        """Test creation of provider with a callable."""
 | 
				
			||||||
        self.assertTrue(providers.Factory(credits))
 | 
					        self.assertTrue(providers.Factory(credits))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_init_with_valid_provided_type(self):
 | 
				
			||||||
 | 
					        """Test creation with not valid provided type."""
 | 
				
			||||||
 | 
					        class ExampleFactory(providers.Factory):
 | 
				
			||||||
 | 
					            """Example factory."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            provided_type = Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        example_factory = ExampleFactory(Example, 1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(example_factory(), Example)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_init_with_valid_provided_subtype(self):
 | 
				
			||||||
 | 
					        """Test creation with not valid provided type."""
 | 
				
			||||||
 | 
					        class ExampleFactory(providers.Factory):
 | 
				
			||||||
 | 
					            """Example factory."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            provided_type = Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class NewExampe(Example):
 | 
				
			||||||
 | 
					            """Example class subclass."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        example_factory = ExampleFactory(NewExampe, 1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIsInstance(example_factory(), NewExampe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_init_with_invalid_provided_type(self):
 | 
				
			||||||
 | 
					        """Test creation with not valid provided type."""
 | 
				
			||||||
 | 
					        class ExampleFactory(providers.Factory):
 | 
				
			||||||
 | 
					            """Example factory."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            provided_type = Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with self.assertRaises(errors.Error):
 | 
				
			||||||
 | 
					            ExampleFactory(list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_init_with_not_callable(self):
 | 
					    def test_init_with_not_callable(self):
 | 
				
			||||||
        """Test creation of provider with not a callable."""
 | 
					        """Test creation of provider with not a callable."""
 | 
				
			||||||
        self.assertRaises(errors.Error, providers.Factory, 123)
 | 
					        self.assertRaises(errors.Error, providers.Factory, 123)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user