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 wire(self, modules: Optional[Iterable[ModuleType]] = None, packages: Optional[Iterable[ModuleType]] = None) -> None: ...
|
||||
def unwire(self) -> None: ...
|
||||
def init_resources(self) -> None: ...
|
||||
def shutdown_resources(self) -> None: ...
|
||||
|
||||
|
||||
class DynamicContainer(Container): ...
|
||||
|
|
|
@ -7,6 +7,7 @@ import six
|
|||
from .errors import Error
|
||||
from .providers cimport (
|
||||
Provider,
|
||||
Resource,
|
||||
deepcopy,
|
||||
)
|
||||
|
||||
|
@ -213,6 +214,19 @@ class DynamicContainer(object):
|
|||
self.wired_to_modules.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):
|
||||
|
|
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)
|
||||
|
||||
|
||||
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 object __container_cls
|
||||
cdef dict __overriding_providers
|
||||
|
|
|
@ -13,8 +13,11 @@ from typing import (
|
|||
Optional,
|
||||
Union,
|
||||
Coroutine as _Coroutine,
|
||||
Generator as _Generator,
|
||||
)
|
||||
|
||||
from . import resources
|
||||
|
||||
|
||||
Injection = Any
|
||||
T = TypeVar('T')
|
||||
|
@ -274,6 +277,34 @@ class Dict(Provider):
|
|||
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):
|
||||
|
||||
def __init__(self, container_cls: Type[T], container: Optional[T] = None, **overriding_providers: Provider) -> None: ...
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
import contextlib
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
@ -37,6 +39,7 @@ from .errors import (
|
|||
Error,
|
||||
NoSuchProviderError,
|
||||
)
|
||||
from . import resources
|
||||
|
||||
cimport cython
|
||||
|
||||
|
@ -2551,6 +2554,200 @@ cdef class Dict(Provider):
|
|||
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):
|
||||
"""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