mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Implement lazy initialization and improve copying for Dependency provider
This commit is contained in:
		
							parent
							
								
									f7fcb22139
								
							
						
					
					
						commit
						17ecd6c8c0
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -102,10 +102,15 @@ class Delegate(Provider[Provider]):
 | 
				
			||||||
class Dependency(Provider[T]):
 | 
					class Dependency(Provider[T]):
 | 
				
			||||||
    def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
 | 
					    def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
 | 
				
			||||||
    def __getattr__(self, name: str) -> Any: ...
 | 
					    def __getattr__(self, name: str) -> Any: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def instance_of(self) -> Type[T]: ...
 | 
					    def instance_of(self) -> Type[T]: ...
 | 
				
			||||||
 | 
					    def set_instance_of(self, instance_of: Type[T]) -> Dependency[T]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def default(self) -> Provider[T]: ...
 | 
					    def default(self) -> Provider[T]: ...
 | 
				
			||||||
 | 
					    def set_default(self, default: Optional[Union[Provider, Any]]) -> Dependency[T]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def is_defined(self) -> bool: ...
 | 
					    def is_defined(self) -> bool: ...
 | 
				
			||||||
    def provided_by(self, provider: Provider) -> OverridingContext[P]: ...
 | 
					    def provided_by(self, provider: Provider) -> OverridingContext[P]: ...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -619,20 +619,13 @@ cdef class Dependency(Provider):
 | 
				
			||||||
        :type: type
 | 
					        :type: type
 | 
				
			||||||
   """
 | 
					   """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, object instance_of=object, default=UNDEFINED):
 | 
					    def __init__(self, object instance_of=object, default=None):
 | 
				
			||||||
        """Initializer."""
 | 
					        """Initialize provider."""
 | 
				
			||||||
        if not isinstance(instance_of, CLASS_TYPES):
 | 
					        self.__instance_of = None
 | 
				
			||||||
            raise TypeError(
 | 
					        self.set_instance_of(instance_of)
 | 
				
			||||||
                'Argument \'instance_of\' has incorrect type (expected {0}, got {1}))'.format(
 | 
					 | 
				
			||||||
                    CLASS_TYPES,
 | 
					 | 
				
			||||||
                    instance_of,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        self.__instance_of = instance_of
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if default is not UNDEFINED and not isinstance(default, Provider):
 | 
					        self.__default = None
 | 
				
			||||||
            default = Object(default)
 | 
					        self.set_default(default)
 | 
				
			||||||
        self.__default = default
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__parent = None
 | 
					        self.__parent = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -644,14 +637,9 @@ cdef class Dependency(Provider):
 | 
				
			||||||
        if copied is not None:
 | 
					        if copied is not None:
 | 
				
			||||||
            return copied
 | 
					            return copied
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        copied_default = (
 | 
					        copied = _memorized_duplicate(self, memo)
 | 
				
			||||||
            deepcopy(self.__default, memo)
 | 
					        copied.set_instance_of(self.instance_of)
 | 
				
			||||||
            if self.__default is not UNDEFINED
 | 
					        copied.set_default(deepcopy(self.default, memo))
 | 
				
			||||||
            else UNDEFINED
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        copied = self.__class__(self.__instance_of, copied_default)
 | 
					 | 
				
			||||||
        memo[id(self)] = copied
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._copy_parent(copied, memo)
 | 
					        self._copy_parent(copied, memo)
 | 
				
			||||||
        self._copy_overridings(copied, memo)
 | 
					        self._copy_overridings(copied, memo)
 | 
				
			||||||
| 
						 | 
					@ -667,7 +655,7 @@ cdef class Dependency(Provider):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if self.__last_overriding:
 | 
					        if self.__last_overriding:
 | 
				
			||||||
            result = self.__last_overriding(*args, **kwargs)
 | 
					            result = self.__last_overriding(*args, **kwargs)
 | 
				
			||||||
        elif not self.__last_overriding and self.__default is not UNDEFINED:
 | 
					        elif self.__default:
 | 
				
			||||||
            result = self.__default(*args, **kwargs)
 | 
					            result = self.__default(*args, **kwargs)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._raise_undefined_error()
 | 
					            self._raise_undefined_error()
 | 
				
			||||||
| 
						 | 
					@ -700,7 +688,7 @@ cdef class Dependency(Provider):
 | 
				
			||||||
    def __getattr__(self, name):
 | 
					    def __getattr__(self, name):
 | 
				
			||||||
        if self.__last_overriding:
 | 
					        if self.__last_overriding:
 | 
				
			||||||
            return getattr(self.__last_overriding, name)
 | 
					            return getattr(self.__last_overriding, name)
 | 
				
			||||||
        elif self.__default is not UNDEFINED:
 | 
					        elif self.__default:
 | 
				
			||||||
            return getattr(self.__default, name)
 | 
					            return getattr(self.__default, name)
 | 
				
			||||||
        raise AttributeError(f'Provider "{self.__class__.__name__}" has no attribute "{name}"')
 | 
					        raise AttributeError(f'Provider "{self.__class__.__name__}" has no attribute "{name}"')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -725,18 +713,37 @@ cdef class Dependency(Provider):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def instance_of(self):
 | 
					    def instance_of(self):
 | 
				
			||||||
        """Return class of required dependency."""
 | 
					        """Return type."""
 | 
				
			||||||
        return self.__instance_of
 | 
					        return self.__instance_of
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_instance_of(self, instance_of):
 | 
				
			||||||
 | 
					        """Set type."""
 | 
				
			||||||
 | 
					        if not isinstance(instance_of, CLASS_TYPES):
 | 
				
			||||||
 | 
					            raise TypeError(
 | 
				
			||||||
 | 
					                '"instance_of" has incorrect type (expected {0}, got {1}))'.format(
 | 
				
			||||||
 | 
					                    CLASS_TYPES,
 | 
				
			||||||
 | 
					                    instance_of,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        self.__instance_of = instance_of
 | 
				
			||||||
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def default(self):
 | 
					    def default(self):
 | 
				
			||||||
        """Return default provider."""
 | 
					        """Return default provider."""
 | 
				
			||||||
        return self.__default
 | 
					        return self.__default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_default(self, default):
 | 
				
			||||||
 | 
					        """Set type."""
 | 
				
			||||||
 | 
					        if default and not isinstance(default, Provider):
 | 
				
			||||||
 | 
					            default = Object(default)
 | 
				
			||||||
 | 
					        self.__default = default
 | 
				
			||||||
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def is_defined(self):
 | 
					    def is_defined(self):
 | 
				
			||||||
        """Return True if dependency is defined."""
 | 
					        """Return True if dependency is defined."""
 | 
				
			||||||
        return self.__last_overriding or self.__default is not UNDEFINED
 | 
					        return self.__last_overriding or self.__default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def provided_by(self, provider):
 | 
					    def provided_by(self, provider):
 | 
				
			||||||
        """Set external dependency provider.
 | 
					        """Set external dependency provider.
 | 
				
			||||||
| 
						 | 
					@ -751,7 +758,7 @@ cdef class Dependency(Provider):
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def related(self):
 | 
					    def related(self):
 | 
				
			||||||
        """Return related providers generator."""
 | 
					        """Return related providers generator."""
 | 
				
			||||||
        if self.__default is not UNDEFINED:
 | 
					        if self.__default:
 | 
				
			||||||
            yield self.__default
 | 
					            yield self.__default
 | 
				
			||||||
        yield from super().related
 | 
					        yield from super().related
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -335,6 +335,24 @@ class DependencyTests(unittest.TestCase):
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.provider = providers.Dependency(instance_of=list)
 | 
					        self.provider = providers.Dependency(instance_of=list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_init_optional(self):
 | 
				
			||||||
 | 
					        list_provider = providers.List(1, 2, 3)
 | 
				
			||||||
 | 
					        provider = providers.Dependency()
 | 
				
			||||||
 | 
					        provider.set_instance_of(list)
 | 
				
			||||||
 | 
					        provider.set_default(list_provider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertIs(provider.instance_of, list)
 | 
				
			||||||
 | 
					        self.assertIs(provider.default, list_provider)
 | 
				
			||||||
 | 
					        self.assertEqual(provider(), [1, 2, 3])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_set_instance_of_returns_self(self):
 | 
				
			||||||
 | 
					        provider = providers.Dependency()
 | 
				
			||||||
 | 
					        self.assertIs(provider.set_instance_of(list), provider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_set_default_returns_self(self):
 | 
				
			||||||
 | 
					        provider = providers.Dependency()
 | 
				
			||||||
 | 
					        self.assertIs(provider.set_default(providers.Provider()), provider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_init_with_not_class(self):
 | 
					    def test_init_with_not_class(self):
 | 
				
			||||||
        self.assertRaises(TypeError, providers.Dependency, object())
 | 
					        self.assertRaises(TypeError, providers.Dependency, object())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user