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]):
 | 
			
		||||
    def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
 | 
			
		||||
    def __getattr__(self, name: str) -> Any: ...
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def instance_of(self) -> Type[T]: ...
 | 
			
		||||
    def set_instance_of(self, instance_of: Type[T]) -> Dependency[T]: ...
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def default(self) -> Provider[T]: ...
 | 
			
		||||
    def set_default(self, default: Optional[Union[Provider, Any]]) -> Dependency[T]: ...
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_defined(self) -> bool: ...
 | 
			
		||||
    def provided_by(self, provider: Provider) -> OverridingContext[P]: ...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -619,20 +619,13 @@ cdef class Dependency(Provider):
 | 
			
		|||
        :type: type
 | 
			
		||||
   """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, object instance_of=object, default=UNDEFINED):
 | 
			
		||||
        """Initializer."""
 | 
			
		||||
        if not isinstance(instance_of, CLASS_TYPES):
 | 
			
		||||
            raise TypeError(
 | 
			
		||||
                'Argument \'instance_of\' has incorrect type (expected {0}, got {1}))'.format(
 | 
			
		||||
                    CLASS_TYPES,
 | 
			
		||||
                    instance_of,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        self.__instance_of = instance_of
 | 
			
		||||
    def __init__(self, object instance_of=object, default=None):
 | 
			
		||||
        """Initialize provider."""
 | 
			
		||||
        self.__instance_of = None
 | 
			
		||||
        self.set_instance_of(instance_of)
 | 
			
		||||
 | 
			
		||||
        if default is not UNDEFINED and not isinstance(default, Provider):
 | 
			
		||||
            default = Object(default)
 | 
			
		||||
        self.__default = default
 | 
			
		||||
        self.__default = None
 | 
			
		||||
        self.set_default(default)
 | 
			
		||||
 | 
			
		||||
        self.__parent = None
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -644,14 +637,9 @@ cdef class Dependency(Provider):
 | 
			
		|||
        if copied is not None:
 | 
			
		||||
            return copied
 | 
			
		||||
 | 
			
		||||
        copied_default = (
 | 
			
		||||
            deepcopy(self.__default, memo)
 | 
			
		||||
            if self.__default is not UNDEFINED
 | 
			
		||||
            else UNDEFINED
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        copied = self.__class__(self.__instance_of, copied_default)
 | 
			
		||||
        memo[id(self)] = copied
 | 
			
		||||
        copied = _memorized_duplicate(self, memo)
 | 
			
		||||
        copied.set_instance_of(self.instance_of)
 | 
			
		||||
        copied.set_default(deepcopy(self.default, memo))
 | 
			
		||||
 | 
			
		||||
        self._copy_parent(copied, memo)
 | 
			
		||||
        self._copy_overridings(copied, memo)
 | 
			
		||||
| 
						 | 
				
			
			@ -667,7 +655,7 @@ cdef class Dependency(Provider):
 | 
			
		|||
        """
 | 
			
		||||
        if self.__last_overriding:
 | 
			
		||||
            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)
 | 
			
		||||
        else:
 | 
			
		||||
            self._raise_undefined_error()
 | 
			
		||||
| 
						 | 
				
			
			@ -700,7 +688,7 @@ cdef class Dependency(Provider):
 | 
			
		|||
    def __getattr__(self, name):
 | 
			
		||||
        if self.__last_overriding:
 | 
			
		||||
            return getattr(self.__last_overriding, name)
 | 
			
		||||
        elif self.__default is not UNDEFINED:
 | 
			
		||||
        elif self.__default:
 | 
			
		||||
            return getattr(self.__default, name)
 | 
			
		||||
        raise AttributeError(f'Provider "{self.__class__.__name__}" has no attribute "{name}"')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -725,18 +713,37 @@ cdef class Dependency(Provider):
 | 
			
		|||
 | 
			
		||||
    @property
 | 
			
		||||
    def instance_of(self):
 | 
			
		||||
        """Return class of required dependency."""
 | 
			
		||||
        """Return type."""
 | 
			
		||||
        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
 | 
			
		||||
    def default(self):
 | 
			
		||||
        """Return default provider."""
 | 
			
		||||
        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
 | 
			
		||||
    def is_defined(self):
 | 
			
		||||
        """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):
 | 
			
		||||
        """Set external dependency provider.
 | 
			
		||||
| 
						 | 
				
			
			@ -751,7 +758,7 @@ cdef class Dependency(Provider):
 | 
			
		|||
    @property
 | 
			
		||||
    def related(self):
 | 
			
		||||
        """Return related providers generator."""
 | 
			
		||||
        if self.__default is not UNDEFINED:
 | 
			
		||||
        if self.__default:
 | 
			
		||||
            yield self.__default
 | 
			
		||||
        yield from super().related
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -335,6 +335,24 @@ class DependencyTests(unittest.TestCase):
 | 
			
		|||
    def setUp(self):
 | 
			
		||||
        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):
 | 
			
		||||
        self.assertRaises(TypeError, providers.Dependency, object())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user