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