mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-26 11:33:58 +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