mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 18:07:44 +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