mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-14 18:40:52 +03:00
Add prototype
This commit is contained in:
parent
b54bcb7b31
commit
79df45ff48
File diff suppressed because it is too large
Load Diff
|
@ -25,6 +25,8 @@ class Container:
|
||||||
def resolve_provider_name(self, provider_to_resolve: Provider) -> Optional[str]: ...
|
def resolve_provider_name(self, provider_to_resolve: Provider) -> Optional[str]: ...
|
||||||
def wire(self, modules: Optional[Iterable[ModuleType]] = None, packages: Optional[Iterable[ModuleType]] = None) -> None: ...
|
def wire(self, modules: Optional[Iterable[ModuleType]] = None, packages: Optional[Iterable[ModuleType]] = None) -> None: ...
|
||||||
def unwire(self) -> None: ...
|
def unwire(self) -> None: ...
|
||||||
|
def init_resources(self) -> None: ...
|
||||||
|
def shutdown_resources(self) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class DynamicContainer(Container): ...
|
class DynamicContainer(Container): ...
|
||||||
|
|
|
@ -7,6 +7,7 @@ import six
|
||||||
from .errors import Error
|
from .errors import Error
|
||||||
from .providers cimport (
|
from .providers cimport (
|
||||||
Provider,
|
Provider,
|
||||||
|
Resource,
|
||||||
deepcopy,
|
deepcopy,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -213,6 +214,19 @@ class DynamicContainer(object):
|
||||||
self.wired_to_modules.clear()
|
self.wired_to_modules.clear()
|
||||||
self.wired_to_packages.clear()
|
self.wired_to_packages.clear()
|
||||||
|
|
||||||
|
def init_resources(self):
|
||||||
|
"""Initialize all container resources."""
|
||||||
|
for provider in self.providers.values():
|
||||||
|
if not isinstance(provider, Resource):
|
||||||
|
continue
|
||||||
|
provider.init()
|
||||||
|
|
||||||
|
def shutdown_resources(self):
|
||||||
|
"""Shutdown all container resources."""
|
||||||
|
for provider in self.providers.values():
|
||||||
|
if not isinstance(provider, Resource):
|
||||||
|
continue
|
||||||
|
provider.shutdown()
|
||||||
|
|
||||||
|
|
||||||
class DeclarativeContainerMetaClass(type):
|
class DeclarativeContainerMetaClass(type):
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -191,6 +191,21 @@ cdef class Dict(Provider):
|
||||||
cpdef object _provide(self, tuple args, dict kwargs)
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Resource(Provider):
|
||||||
|
cdef object __initializer
|
||||||
|
cdef bint __initialized
|
||||||
|
cdef object __shutdowner
|
||||||
|
cdef object __resource
|
||||||
|
|
||||||
|
cdef tuple __args
|
||||||
|
cdef int __args_len
|
||||||
|
|
||||||
|
cdef tuple __kwargs
|
||||||
|
cdef int __kwargs_len
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
cdef class Container(Provider):
|
cdef class Container(Provider):
|
||||||
cdef object __container_cls
|
cdef object __container_cls
|
||||||
cdef dict __overriding_providers
|
cdef dict __overriding_providers
|
||||||
|
|
|
@ -13,8 +13,11 @@ from typing import (
|
||||||
Optional,
|
Optional,
|
||||||
Union,
|
Union,
|
||||||
Coroutine as _Coroutine,
|
Coroutine as _Coroutine,
|
||||||
|
Generator as _Generator,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from . import resources
|
||||||
|
|
||||||
|
|
||||||
Injection = Any
|
Injection = Any
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
@ -274,6 +277,34 @@ class Dict(Provider):
|
||||||
def clear_kwargs(self) -> Dict: ...
|
def clear_kwargs(self) -> Dict: ...
|
||||||
|
|
||||||
|
|
||||||
|
class Resource(Provider, Generic[T]):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
initializer: Union[
|
||||||
|
resources.Resource,
|
||||||
|
_Generator[T, ..., ...],
|
||||||
|
_Callable[..., T],
|
||||||
|
],
|
||||||
|
*args: Injection,
|
||||||
|
**kwargs: Injection,
|
||||||
|
): ...
|
||||||
|
def __call__(self, *args: Injection, **kwargs: Injection) -> T: ...
|
||||||
|
@property
|
||||||
|
def args(self) -> Tuple[Injection]: ...
|
||||||
|
def add_args(self, *args: Injection) -> Resource: ...
|
||||||
|
def set_args(self, *args: Injection) -> Resource: ...
|
||||||
|
def clear_args(self) -> Resource: ...
|
||||||
|
@property
|
||||||
|
def kwargs(self) -> _Dict[Any, Injection]: ...
|
||||||
|
def add_kwargs(self, **kwargs: Injection) -> Resource: ...
|
||||||
|
def set_kwargs(self, **kwargs: Injection) -> Resource: ...
|
||||||
|
def clear_kwargs(self) -> Resource: ...
|
||||||
|
@property
|
||||||
|
def initialized(self) -> bool: ...
|
||||||
|
def init(self) -> T: ...
|
||||||
|
def shutdown(self) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class Container(Provider):
|
class Container(Provider):
|
||||||
|
|
||||||
def __init__(self, container_cls: Type[T], container: Optional[T] = None, **overriding_providers: Provider) -> None: ...
|
def __init__(self, container_cls: Type[T], container: Optional[T] = None, **overriding_providers: Provider) -> None: ...
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import contextlib
|
||||||
|
import inspect
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -37,6 +39,7 @@ from .errors import (
|
||||||
Error,
|
Error,
|
||||||
NoSuchProviderError,
|
NoSuchProviderError,
|
||||||
)
|
)
|
||||||
|
from . import resources
|
||||||
|
|
||||||
cimport cython
|
cimport cython
|
||||||
|
|
||||||
|
@ -2551,6 +2554,200 @@ cdef class Dict(Provider):
|
||||||
return __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len)
|
return __provide_keyword_args(kwargs, self.__kwargs, self.__kwargs_len)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Resource(Provider):
|
||||||
|
"""Resource provider provides a component with initialization and shutdown."""
|
||||||
|
|
||||||
|
def __init__(self, initializer, *args, **kwargs):
|
||||||
|
self.__initializer = initializer
|
||||||
|
self.__initialized = False
|
||||||
|
self.__resource = None
|
||||||
|
self.__shutdowner = None
|
||||||
|
|
||||||
|
self.__args = tuple()
|
||||||
|
self.__args_len = 0
|
||||||
|
self.set_args(*args)
|
||||||
|
|
||||||
|
self.__kwargs = tuple()
|
||||||
|
self.__kwargs_len = 0
|
||||||
|
self.set_kwargs(**kwargs)
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def __deepcopy__(self, memo):
|
||||||
|
"""Create and return full copy of provider."""
|
||||||
|
copied = memo.get(id(self))
|
||||||
|
if copied is not None:
|
||||||
|
return copied
|
||||||
|
|
||||||
|
if self.__initialized:
|
||||||
|
raise Error('Can not copy initialized resource')
|
||||||
|
|
||||||
|
copied = self.__class__(
|
||||||
|
self.__initializer,
|
||||||
|
*deepcopy(self.args, memo),
|
||||||
|
**deepcopy(self.kwargs, memo),
|
||||||
|
)
|
||||||
|
self._copy_overridings(copied, memo)
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return (
|
||||||
|
f'{self.__class__.__name__}(\'{self.__initializer}\', '
|
||||||
|
f'initialized={self.__initialized})'
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def args(self):
|
||||||
|
"""Return positional argument injections."""
|
||||||
|
cdef int index
|
||||||
|
cdef PositionalInjection arg
|
||||||
|
cdef list args
|
||||||
|
|
||||||
|
args = list()
|
||||||
|
for index in range(self.__args_len):
|
||||||
|
arg = self.__args[index]
|
||||||
|
args.append(arg.__value)
|
||||||
|
return tuple(args)
|
||||||
|
|
||||||
|
def add_args(self, *args):
|
||||||
|
"""Add positional argument injections.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__args += parse_positional_injections(args)
|
||||||
|
self.__args_len = len(self.__args)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def set_args(self, *args):
|
||||||
|
"""Set positional argument injections.
|
||||||
|
|
||||||
|
Existing positional argument injections are dropped.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__args = parse_positional_injections(args)
|
||||||
|
self.__args_len = len(self.__args)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def clear_args(self):
|
||||||
|
"""Drop positional argument injections.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__args = tuple()
|
||||||
|
self.__args_len = len(self.__args)
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kwargs(self):
|
||||||
|
"""Return keyword argument injections."""
|
||||||
|
cdef int index
|
||||||
|
cdef NamedInjection kwarg
|
||||||
|
cdef dict kwargs
|
||||||
|
|
||||||
|
kwargs = dict()
|
||||||
|
for index in range(self.__kwargs_len):
|
||||||
|
kwarg = self.__kwargs[index]
|
||||||
|
kwargs[kwarg.__name] = kwarg.__value
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def add_kwargs(self, **kwargs):
|
||||||
|
"""Add keyword argument injections.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__kwargs += parse_named_injections(kwargs)
|
||||||
|
self.__kwargs_len = len(self.__kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def set_kwargs(self, **kwargs):
|
||||||
|
"""Set keyword argument injections.
|
||||||
|
|
||||||
|
Existing keyword argument injections are dropped.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__kwargs = parse_named_injections(kwargs)
|
||||||
|
self.__kwargs_len = len(self.__kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def clear_kwargs(self):
|
||||||
|
"""Drop keyword argument injections.
|
||||||
|
|
||||||
|
:return: Reference ``self``
|
||||||
|
"""
|
||||||
|
self.__kwargs = tuple()
|
||||||
|
self.__kwargs_len = len(self.__kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def initialized(self):
|
||||||
|
"""Check if resource is initialized."""
|
||||||
|
return self.__initialized
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
"""Initialize resource."""
|
||||||
|
return self.__call__()
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
"""Shutdown resource."""
|
||||||
|
if not self.__initialized:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.__shutdowner:
|
||||||
|
with contextlib.suppress(StopIteration):
|
||||||
|
self.__shutdowner(self.__resource)
|
||||||
|
|
||||||
|
self.__resource = None
|
||||||
|
self.__initialized = False
|
||||||
|
self.__shutdowner = None
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs):
|
||||||
|
if self.__initialized:
|
||||||
|
return self.__resource
|
||||||
|
|
||||||
|
if isinstance(self.__initializer, resources.Resource):
|
||||||
|
initializer = self.__initializer()
|
||||||
|
self.__resource = __call(
|
||||||
|
initializer.init,
|
||||||
|
args,
|
||||||
|
self.__args,
|
||||||
|
self.__args_len,
|
||||||
|
kwargs,
|
||||||
|
self.__kwargs,
|
||||||
|
self.__kwargs_len,
|
||||||
|
)
|
||||||
|
self.__shutdowner = initializer.shutdown
|
||||||
|
elif inspect.isgeneratorfunction(self.__initializer):
|
||||||
|
initializer = __call(
|
||||||
|
self.__initializer,
|
||||||
|
args,
|
||||||
|
self.__args,
|
||||||
|
self.__args_len,
|
||||||
|
kwargs,
|
||||||
|
self.__kwargs,
|
||||||
|
self.__kwargs_len,
|
||||||
|
)
|
||||||
|
self.__resource = initializer.__next__()
|
||||||
|
self.__shutdowner = initializer.send
|
||||||
|
elif callable(self.__initializer):
|
||||||
|
self.__resource = __call(
|
||||||
|
self.__initializer,
|
||||||
|
args,
|
||||||
|
self.__args,
|
||||||
|
self.__args_len,
|
||||||
|
kwargs,
|
||||||
|
self.__kwargs,
|
||||||
|
self.__kwargs_len,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise Error('Unknown type of resource initializer')
|
||||||
|
|
||||||
|
self.__initialized = True
|
||||||
|
return self.__resource
|
||||||
|
|
||||||
|
|
||||||
cdef class Container(Provider):
|
cdef class Container(Provider):
|
||||||
"""Container provider provides an instance of declarative container.
|
"""Container provider provides an instance of declarative container.
|
||||||
|
|
||||||
|
|
31
src/dependency_injector/resources.py
Normal file
31
src/dependency_injector/resources.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
"""Resources module."""
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import sys
|
||||||
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
|
from typing import GenericMeta
|
||||||
|
else:
|
||||||
|
class GenericMeta(type):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceMeta(GenericMeta, abc.ABCMeta):
|
||||||
|
def __getitem__(cls, item):
|
||||||
|
# Spike for Python 3.6
|
||||||
|
return cls(item)
|
||||||
|
|
||||||
|
|
||||||
|
class Resource(Generic[T], metaclass=ResourceMeta):
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def init(self, *args, **kwargs) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def shutdown(self, resource: T) -> None:
|
||||||
|
...
|
Loading…
Reference in New Issue
Block a user