Implement lazy initialization and improve copying for ProvidedInstance provider

This commit is contained in:
Roman Mogylatov 2021-03-09 17:23:58 -05:00
parent bb473ab91e
commit cec342c1e4
6 changed files with 1473 additions and 1328 deletions

View File

@ -1389,12 +1389,12 @@ struct __pyx_obj_19dependency_injector_9providers_Selector {
* # Provided instance * # Provided instance
* *
* cdef class ProvidedInstance(Provider): # <<<<<<<<<<<<<< * cdef class ProvidedInstance(Provider): # <<<<<<<<<<<<<<
* cdef Provider __provider * cdef object __provides
* *
*/ */
struct __pyx_obj_19dependency_injector_9providers_ProvidedInstance { struct __pyx_obj_19dependency_injector_9providers_ProvidedInstance {
struct __pyx_obj_19dependency_injector_9providers_Provider __pyx_base; struct __pyx_obj_19dependency_injector_9providers_Provider __pyx_base;
struct __pyx_obj_19dependency_injector_9providers_Provider *__pyx___provider; PyObject *__pyx___provides;
}; };
@ -2144,7 +2144,7 @@ static struct __pyx_vtabstruct_19dependency_injector_9providers_Selector *__pyx_
* # Provided instance * # Provided instance
* *
* cdef class ProvidedInstance(Provider): # <<<<<<<<<<<<<< * cdef class ProvidedInstance(Provider): # <<<<<<<<<<<<<<
* cdef Provider __provider * cdef object __provides
* *
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -235,7 +235,7 @@ cdef class Selector(Provider):
# Provided instance # Provided instance
cdef class ProvidedInstance(Provider): cdef class ProvidedInstance(Provider):
cdef Provider __provider cdef object __provides
cpdef object _provide(self, tuple args, dict kwargs) cpdef object _provide(self, tuple args, dict kwargs)

View File

@ -423,10 +423,13 @@ class ProvidedInstanceFluentInterface:
def __getattr__(self, item: Any) -> AttributeGetter: ... def __getattr__(self, item: Any) -> AttributeGetter: ...
def __getitem__(self, item: Any) -> ItemGetter: ... def __getitem__(self, item: Any) -> ItemGetter: ...
def call(self, *args: Injection, **kwargs: Injection) -> MethodCaller: ... def call(self, *args: Injection, **kwargs: Injection) -> MethodCaller: ...
@property
def provides(self) -> Optional[Provider]: ...
def set_provides(self, provides: Optional[Provider]) -> ProvidedInstanceFluentInterface: ...
class ProvidedInstance(Provider, ProvidedInstanceFluentInterface): class ProvidedInstance(Provider, ProvidedInstanceFluentInterface):
def __init__(self, provider: Provider) -> None: ... def __init__(self, provides: Optional[Provider] = None) -> None: ...
class AttributeGetter(Provider, ProvidedInstanceFluentInterface): class AttributeGetter(Provider, ProvidedInstanceFluentInterface):

View File

@ -3886,23 +3886,22 @@ cdef class ProvidedInstance(Provider):
- :py:class:`Dependency` - :py:class:`Dependency`
""" """
def __init__(self, provider): def __init__(self, provides=None):
self.__provider = provider self.__provides = None
self.set_provides(provides)
super().__init__() super().__init__()
def __repr__(self): def __repr__(self):
return f'{self.__class__.__name__}(\'{self.__provider}\')' return f'{self.__class__.__name__}(\'{self.__provides}\')'
def __deepcopy__(self, memo=None): def __deepcopy__(self, memo=None):
cdef ProvidedInstance copied
copied = memo.get(id(self)) copied = memo.get(id(self))
if copied is not None: if copied is not None:
return copied return copied
return self.__class__( copied = _memorized_duplicate(self, memo)
deepcopy(self.__provider, memo), copied.set_provides(_copy_if_provider(self.provides, memo))
) return copied
def __getattr__(self, item): def __getattr__(self, item):
return AttributeGetter(self, item) return AttributeGetter(self, item)
@ -3912,8 +3911,13 @@ cdef class ProvidedInstance(Provider):
@property @property
def provides(self): def provides(self):
"""Return provider.""" """Return provider's provides."""
return self.__provider return self.__provides
def set_provides(self, provides):
"""Set provider's provides."""
self.__provides = provides
return self
def call(self, *args, **kwargs): def call(self, *args, **kwargs):
return MethodCaller(self, *args, **kwargs) return MethodCaller(self, *args, **kwargs)
@ -3921,11 +3925,12 @@ cdef class ProvidedInstance(Provider):
@property @property
def related(self): def related(self):
"""Return related providers generator.""" """Return related providers generator."""
yield self.__provider if is_provider(self.provides):
yield self.provides
yield from super().related yield from super().related
cpdef object _provide(self, tuple args, dict kwargs): cpdef object _provide(self, tuple args, dict kwargs):
return self.__provider(*args, **kwargs) return self.__provides(*args, **kwargs)
cdef class AttributeGetter(Provider): cdef class AttributeGetter(Provider):

View File

@ -69,6 +69,16 @@ class ProvidedInstanceTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.container = Container() self.container = Container()
def test_lazy_init(self):
provides = providers.Object(object())
provider = providers.ProvidedInstance()
provider.set_provides(provides)
self.assertIs(provider.provides, provides)
def test_set_provides_returns_self(self):
provider = providers.ProvidedInstance()
self.assertIs(provider.set_provides(providers.Provider()), provider)
def test_is_provider(self): def test_is_provider(self):
self.assertTrue(providers.is_provider(self.container.service.provided)) self.assertTrue(providers.is_provider(self.container.service.provided))