mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-14 18:40:52 +03:00
Implement lazy initialization and improve copying for Resource provider
This commit is contained in:
parent
17ecd6c8c0
commit
f180f493fa
|
@ -1339,12 +1339,12 @@ struct __pyx_obj_19dependency_injector_9providers_Dict {
|
|||
*
|
||||
*
|
||||
* cdef class Resource(Provider): # <<<<<<<<<<<<<<
|
||||
* cdef object __initializer
|
||||
* cdef object __provides
|
||||
* cdef bint __initialized
|
||||
*/
|
||||
struct __pyx_obj_19dependency_injector_9providers_Resource {
|
||||
struct __pyx_obj_19dependency_injector_9providers_Provider __pyx_base;
|
||||
PyObject *__pyx___initializer;
|
||||
PyObject *__pyx___provides;
|
||||
int __pyx___initialized;
|
||||
PyObject *__pyx___shutdowner;
|
||||
PyObject *__pyx___resource;
|
||||
|
@ -2102,7 +2102,7 @@ static struct __pyx_vtabstruct_19dependency_injector_9providers_Dict *__pyx_vtab
|
|||
*
|
||||
*
|
||||
* cdef class Resource(Provider): # <<<<<<<<<<<<<<
|
||||
* cdef object __initializer
|
||||
* cdef object __provides
|
||||
* cdef bint __initialized
|
||||
*/
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -203,7 +203,7 @@ cdef class Dict(Provider):
|
|||
|
||||
|
||||
cdef class Resource(Provider):
|
||||
cdef object __initializer
|
||||
cdef object __provides
|
||||
cdef bint __initialized
|
||||
cdef object __shutdowner
|
||||
cdef object __resource
|
||||
|
|
|
@ -351,19 +351,20 @@ class Dict(Provider[_Dict]):
|
|||
|
||||
class Resource(Provider[T]):
|
||||
@overload
|
||||
def __init__(self, initializer: Type[resources.Resource[T]], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[Type[resources.Resource[T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@overload
|
||||
def __init__(self, initializer: Type[resources.AsyncResource[T]], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[Type[resources.AsyncResource[T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@overload
|
||||
def __init__(self, initializer: _Callable[..., _Iterator[T]], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[_Callable[..., _Iterator[T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@overload
|
||||
def __init__(self, initializer: _Callable[..., _AsyncIterator[T]], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[_Callable[..., _AsyncIterator[T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@overload
|
||||
def __init__(self, initializer: _Callable[..., _Coroutine[Injection, Injection, T]], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[_Callable[..., _Coroutine[Injection, Injection, T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@overload
|
||||
def __init__(self, initializer: _Callable[..., T], *args: Injection, **kwargs: Injection) -> None: ...
|
||||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||
@property
|
||||
def initializer(self) -> _Callable[..., Any]: ...
|
||||
def provides(self) -> Optional[_Callable[..., Any]]: ...
|
||||
def set_provides(self, provides: Optional[Any]) -> Resource[T]: ...
|
||||
@property
|
||||
def args(self) -> Tuple[Injection]: ...
|
||||
def add_args(self, *args: Injection) -> Resource[T]: ...
|
||||
|
|
|
@ -3218,8 +3218,10 @@ cdef class Dict(Provider):
|
|||
cdef class Resource(Provider):
|
||||
"""Resource provider provides a component with initialization and shutdown."""
|
||||
|
||||
def __init__(self, initializer, *args, **kwargs):
|
||||
self.__initializer = initializer
|
||||
def __init__(self, provides=None, *args, **kwargs):
|
||||
self.__provides = None
|
||||
self.set_provides(provides)
|
||||
|
||||
self.__initialized = False
|
||||
self.__resource = None
|
||||
self.__shutdowner = None
|
||||
|
@ -3243,11 +3245,11 @@ cdef class Resource(Provider):
|
|||
if self.__initialized:
|
||||
raise Error('Can not copy initialized resource')
|
||||
|
||||
copied = self.__class__(
|
||||
self.__initializer,
|
||||
*deepcopy(self.args, memo),
|
||||
**deepcopy(self.kwargs, memo),
|
||||
)
|
||||
copied = _memorized_duplicate(self, memo)
|
||||
copied.set_provides(_copy_if_provider(self.provides, memo))
|
||||
copied.set_args(*deepcopy(self.args, memo))
|
||||
copied.set_kwargs(**deepcopy(self.kwargs, memo))
|
||||
|
||||
self._copy_overridings(copied, memo)
|
||||
|
||||
return copied
|
||||
|
@ -3257,12 +3259,17 @@ cdef class Resource(Provider):
|
|||
|
||||
:rtype: str
|
||||
"""
|
||||
return represent_provider(provider=self, provides=self.__initializer)
|
||||
return represent_provider(provider=self, provides=self.provides)
|
||||
|
||||
@property
|
||||
def initializer(self):
|
||||
"""Return initializer."""
|
||||
return self.__initializer
|
||||
def provides(self):
|
||||
"""Return provider's provides."""
|
||||
return self.__provides
|
||||
|
||||
def set_provides(self, provides):
|
||||
"""Set provider's provides."""
|
||||
self.__provides = provides
|
||||
return self
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
|
@ -3387,7 +3394,7 @@ cdef class Resource(Provider):
|
|||
@property
|
||||
def related(self):
|
||||
"""Return related providers generator."""
|
||||
yield from filter(is_provider, [self.__initializer])
|
||||
yield from filter(is_provider, [self.provides])
|
||||
yield from filter(is_provider, self.args)
|
||||
yield from filter(is_provider, self.kwargs.values())
|
||||
yield from super().related
|
||||
|
@ -3396,8 +3403,8 @@ cdef class Resource(Provider):
|
|||
if self.__initialized:
|
||||
return self.__resource
|
||||
|
||||
if self._is_resource_subclass(self.__initializer):
|
||||
initializer = self.__initializer()
|
||||
if self._is_resource_subclass(self.__provides):
|
||||
initializer = self.__provides()
|
||||
self.__resource = __call(
|
||||
initializer.init,
|
||||
args,
|
||||
|
@ -3408,8 +3415,8 @@ cdef class Resource(Provider):
|
|||
self.__kwargs_len,
|
||||
)
|
||||
self.__shutdowner = initializer.shutdown
|
||||
elif self._is_async_resource_subclass(self.__initializer):
|
||||
initializer = self.__initializer()
|
||||
elif self._is_async_resource_subclass(self.__provides):
|
||||
initializer = self.__provides()
|
||||
async_init = __call(
|
||||
initializer.init,
|
||||
args,
|
||||
|
@ -3421,9 +3428,9 @@ cdef class Resource(Provider):
|
|||
)
|
||||
self.__initialized = True
|
||||
return self._create_init_future(async_init, initializer.shutdown)
|
||||
elif inspect.isgeneratorfunction(self.__initializer):
|
||||
elif inspect.isgeneratorfunction(self.__provides):
|
||||
initializer = __call(
|
||||
self.__initializer,
|
||||
self.__provides,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
|
@ -3433,9 +3440,9 @@ cdef class Resource(Provider):
|
|||
)
|
||||
self.__resource = next(initializer)
|
||||
self.__shutdowner = initializer.send
|
||||
elif iscoroutinefunction(self.__initializer):
|
||||
elif iscoroutinefunction(self.__provides):
|
||||
initializer = __call(
|
||||
self.__initializer,
|
||||
self.__provides,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
|
@ -3445,9 +3452,9 @@ cdef class Resource(Provider):
|
|||
)
|
||||
self.__initialized = True
|
||||
return self._create_init_future(initializer)
|
||||
elif isasyncgenfunction(self.__initializer):
|
||||
elif isasyncgenfunction(self.__provides):
|
||||
initializer = __call(
|
||||
self.__initializer,
|
||||
self.__provides,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
|
@ -3457,9 +3464,9 @@ cdef class Resource(Provider):
|
|||
)
|
||||
self.__initialized = True
|
||||
return self._create_async_gen_init_future(initializer)
|
||||
elif callable(self.__initializer):
|
||||
elif callable(self.__provides):
|
||||
self.__resource = __call(
|
||||
self.__initializer,
|
||||
self.__provides,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
|
@ -4506,6 +4513,12 @@ cpdef object _memorized_duplicate(object instance, dict memo):
|
|||
return copied
|
||||
|
||||
|
||||
cpdef object _copy_if_provider(object instance, dict memo):
|
||||
if not is_provider(instance):
|
||||
return instance
|
||||
return deepcopy(instance, memo)
|
||||
|
||||
|
||||
cpdef str _class_qualname(object instance):
|
||||
name = getattr(instance.__class__, '__qualname__', None)
|
||||
if not name:
|
||||
|
|
|
@ -29,6 +29,16 @@ class ResourceTests(unittest.TestCase):
|
|||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(providers.Resource(init_fn)))
|
||||
|
||||
def test_init_optional_provides(self):
|
||||
provider = providers.Resource()
|
||||
provider.set_provides(init_fn)
|
||||
self.assertIs(provider.provides, init_fn)
|
||||
self.assertEqual(provider(), (tuple(), dict()))
|
||||
|
||||
def test_set_provides_returns_self(self):
|
||||
provider = providers.Resource()
|
||||
self.assertIs(provider.set_provides(init_fn), provider)
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Resource(init_fn)
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
|
Loading…
Reference in New Issue
Block a user