mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-12 01:20:51 +03:00
Merge branch 'release/4.20.0' into master
This commit is contained in:
commit
5e5531765d
|
@ -22,6 +22,7 @@ Containers module API docs - :py:mod:`dependency_injector.containers`.
|
||||||
declarative
|
declarative
|
||||||
dynamic
|
dynamic
|
||||||
specialization
|
specialization
|
||||||
|
inject_self
|
||||||
overriding
|
overriding
|
||||||
reset_singletons
|
reset_singletons
|
||||||
traversal
|
traversal
|
||||||
|
|
20
docs/containers/inject_self.rst
Normal file
20
docs/containers/inject_self.rst
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Injecting container "self"
|
||||||
|
==========================
|
||||||
|
|
||||||
|
You can inject container "self" into container providers.
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/containers/inject_self.py
|
||||||
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
:emphasize-lines: 20, 26
|
||||||
|
|
||||||
|
To inject container "self" you need to define ``Self`` provider. Container can have only one ``Self`` provider.
|
||||||
|
|
||||||
|
Usually you will use name ``__self__``.
|
||||||
|
You can also use different name. When you use different name container will also reference
|
||||||
|
defined ``Self`` provider in ``.__self__`` attribute.
|
||||||
|
|
||||||
|
Provider ``Self`` is not listed in container ``.providers`` attributes.
|
||||||
|
|
||||||
|
.. disqus::
|
||||||
|
|
|
@ -7,6 +7,12 @@ that were made in every particular version.
|
||||||
From version 0.7.6 *Dependency Injector* framework strictly
|
From version 0.7.6 *Dependency Injector* framework strictly
|
||||||
follows `Semantic versioning`_
|
follows `Semantic versioning`_
|
||||||
|
|
||||||
|
4.20.0
|
||||||
|
------
|
||||||
|
- Add container "self" injections.
|
||||||
|
See issue: `#364 <https://github.com/ets-labs/python-dependency-injector/issues/364>`_.
|
||||||
|
Thanks to `@shaunc <https://github.com/shaunc>`_ for suggesting the feature.
|
||||||
|
|
||||||
4.19.0
|
4.19.0
|
||||||
------
|
------
|
||||||
- Add ``singleton.full_reset()`` method to reset all underlying singleton providers.
|
- Add ``singleton.full_reset()`` method to reset all underlying singleton providers.
|
||||||
|
|
36
examples/containers/inject_self.py
Normal file
36
examples/containers/inject_self.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"""Container injecting ``self`` example."""
|
||||||
|
|
||||||
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
|
class Service:
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceDispatcher:
|
||||||
|
def __init__(self, container: containers.Container):
|
||||||
|
self.container = container
|
||||||
|
|
||||||
|
def get_services(self):
|
||||||
|
for provider in self.container.traverse(types=[providers.Factory]):
|
||||||
|
yield provider()
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
__self__ = providers.Self()
|
||||||
|
|
||||||
|
service1 = providers.Factory(Service, name='Service 1')
|
||||||
|
service2 = providers.Factory(Service, name='Service 2')
|
||||||
|
service3 = providers.Factory(Service, name='Service 3')
|
||||||
|
|
||||||
|
dispatcher = providers.Singleton(ServiceDispatcher, __self__)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
dispatcher = container.dispatcher()
|
||||||
|
for service in dispatcher.get_services():
|
||||||
|
print(service.name)
|
|
@ -1,6 +1,6 @@
|
||||||
"""Top-level package."""
|
"""Top-level package."""
|
||||||
|
|
||||||
__version__ = '4.19.0'
|
__version__ = '4.20.0'
|
||||||
"""Version number.
|
"""Version number.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,15 +7,13 @@ from typing import (
|
||||||
Union,
|
Union,
|
||||||
ClassVar,
|
ClassVar,
|
||||||
Callable as _Callable,
|
Callable as _Callable,
|
||||||
Sequence,
|
|
||||||
Iterable,
|
Iterable,
|
||||||
Iterator,
|
|
||||||
TypeVar,
|
TypeVar,
|
||||||
Awaitable,
|
Awaitable,
|
||||||
overload,
|
overload,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .providers import Provider
|
from .providers import Provider, Self
|
||||||
|
|
||||||
|
|
||||||
C_Base = TypeVar('C_Base', bound='Container')
|
C_Base = TypeVar('C_Base', bound='Container')
|
||||||
|
@ -29,12 +27,13 @@ class Container:
|
||||||
providers: Dict[str, Provider]
|
providers: Dict[str, Provider]
|
||||||
dependencies: Dict[str, Provider]
|
dependencies: Dict[str, Provider]
|
||||||
overridden: Tuple[Provider]
|
overridden: Tuple[Provider]
|
||||||
__self__: Provider
|
__self__: Self
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
def __deepcopy__(self, memo: Optional[Dict[str, Any]]) -> Provider: ...
|
def __deepcopy__(self, memo: Optional[Dict[str, Any]]) -> Provider: ...
|
||||||
def __setattr__(self, name: str, value: Union[Provider, Any]) -> None: ...
|
def __setattr__(self, name: str, value: Union[Provider, Any]) -> None: ...
|
||||||
def __delattr__(self, name: str) -> None: ...
|
def __delattr__(self, name: str) -> None: ...
|
||||||
def set_providers(self, **providers: Provider): ...
|
def set_providers(self, **providers: Provider): ...
|
||||||
|
def set_provider(self, name: str, provider: Provider) -> None: ...
|
||||||
def override(self, overriding: C_Base) -> None: ...
|
def override(self, overriding: C_Base) -> None: ...
|
||||||
def override_providers(self, **overriding_providers: Provider) -> None: ...
|
def override_providers(self, **overriding_providers: Provider) -> None: ...
|
||||||
def reset_last_overriding(self) -> None: ...
|
def reset_last_overriding(self) -> None: ...
|
||||||
|
@ -47,10 +46,10 @@ class Container:
|
||||||
def apply_container_providers_overridings(self) -> None: ...
|
def apply_container_providers_overridings(self) -> None: ...
|
||||||
def reset_singletons(self) -> None: ...
|
def reset_singletons(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def traverse(self, types: Optional[Sequence[TT]] = None) -> Iterator[TT]: ...
|
def traverse(self, types: Optional[Iterable[Type[TT]]] = None) -> _Iterator[TT]: ...
|
||||||
@classmethod
|
@classmethod
|
||||||
@overload
|
@overload
|
||||||
def traverse(cls, types: Optional[Sequence[TT]] = None) -> Iterator[TT]: ...
|
def traverse(self, types: Optional[Iterable[Type[TT]]] = None) -> _Iterator[TT]: ...
|
||||||
|
|
||||||
|
|
||||||
class DynamicContainer(Container): ...
|
class DynamicContainer(Container): ...
|
||||||
|
|
|
@ -69,7 +69,7 @@ class DynamicContainer(Container):
|
||||||
self.declarative_parent = None
|
self.declarative_parent = None
|
||||||
self.wired_to_modules = []
|
self.wired_to_modules = []
|
||||||
self.wired_to_packages = []
|
self.wired_to_packages = []
|
||||||
self.__self__ = providers.Object(self)
|
self.__self__ = providers.Self(self)
|
||||||
super(DynamicContainer, self).__init__()
|
super(DynamicContainer, self).__init__()
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
|
@ -79,12 +79,18 @@ class DynamicContainer(Container):
|
||||||
return copied
|
return copied
|
||||||
|
|
||||||
copied = self.__class__()
|
copied = self.__class__()
|
||||||
|
memo[id(self)] = copied
|
||||||
|
|
||||||
copied.provider_type = providers.Provider
|
copied.provider_type = providers.Provider
|
||||||
copied.overridden = providers.deepcopy(self.overridden, memo)
|
copied.overridden = providers.deepcopy(self.overridden, memo)
|
||||||
copied.declarative_parent = self.declarative_parent
|
copied.declarative_parent = self.declarative_parent
|
||||||
|
|
||||||
|
copied.__self__ = providers.deepcopy(self.__self__, memo)
|
||||||
|
for name in copied.__self__.alt_names:
|
||||||
|
copied.set_provider(name, copied.__self__)
|
||||||
|
|
||||||
for name, provider in providers.deepcopy(self.providers, memo).items():
|
for name, provider in providers.deepcopy(self.providers, memo).items():
|
||||||
setattr(copied, name, provider)
|
copied.set_provider(name, provider)
|
||||||
|
|
||||||
return copied
|
return copied
|
||||||
|
|
||||||
|
@ -102,7 +108,7 @@ class DynamicContainer(Container):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if isinstance(value, providers.Provider) and name != '__self__':
|
if isinstance(value, providers.Provider) and not isinstance(value, providers.Self):
|
||||||
_check_provider_type(self, value)
|
_check_provider_type(self, value)
|
||||||
self.providers[name] = value
|
self.providers[name] = value
|
||||||
super(DynamicContainer, self).__setattr__(name, value)
|
super(DynamicContainer, self).__setattr__(name, value)
|
||||||
|
@ -154,6 +160,19 @@ class DynamicContainer(Container):
|
||||||
for name, provider in six.iteritems(providers):
|
for name, provider in six.iteritems(providers):
|
||||||
setattr(self, name, provider)
|
setattr(self, name, provider)
|
||||||
|
|
||||||
|
def set_provider(self, name, provider):
|
||||||
|
"""Set container provider.
|
||||||
|
|
||||||
|
:param name: Provider name
|
||||||
|
:type name: str
|
||||||
|
|
||||||
|
:param provider: Provider
|
||||||
|
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
setattr(self, name, provider)
|
||||||
|
|
||||||
def override(self, object overriding):
|
def override(self, object overriding):
|
||||||
"""Override current container by overriding container.
|
"""Override current container by overriding container.
|
||||||
|
|
||||||
|
@ -282,6 +301,10 @@ class DeclarativeContainerMetaClass(type):
|
||||||
|
|
||||||
def __new__(type mcs, str class_name, tuple bases, dict attributes):
|
def __new__(type mcs, str class_name, tuple bases, dict attributes):
|
||||||
"""Declarative container class factory."""
|
"""Declarative container class factory."""
|
||||||
|
self = mcs.__fetch_self(attributes)
|
||||||
|
if self is None:
|
||||||
|
self = providers.Self()
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
name: container
|
name: container
|
||||||
for name, container in six.iteritems(attributes)
|
for name, container in six.iteritems(attributes)
|
||||||
|
@ -291,7 +314,7 @@ class DeclarativeContainerMetaClass(type):
|
||||||
cls_providers = {
|
cls_providers = {
|
||||||
name: provider
|
name: provider
|
||||||
for name, provider in six.iteritems(attributes)
|
for name, provider in six.iteritems(attributes)
|
||||||
if isinstance(provider, providers.Provider)
|
if isinstance(provider, providers.Provider) and not isinstance(provider, providers.Self)
|
||||||
}
|
}
|
||||||
|
|
||||||
inherited_providers = {
|
inherited_providers = {
|
||||||
|
@ -312,7 +335,8 @@ class DeclarativeContainerMetaClass(type):
|
||||||
|
|
||||||
cls = <type>type.__new__(mcs, class_name, bases, attributes)
|
cls = <type>type.__new__(mcs, class_name, bases, attributes)
|
||||||
|
|
||||||
cls.__self__ = providers.Object(cls)
|
self.set_container(cls)
|
||||||
|
cls.__self__ = self
|
||||||
|
|
||||||
for provider in six.itervalues(cls.providers):
|
for provider in six.itervalues(cls.providers):
|
||||||
_check_provider_type(cls, provider)
|
_check_provider_type(cls, provider)
|
||||||
|
@ -375,6 +399,28 @@ class DeclarativeContainerMetaClass(type):
|
||||||
"""Return providers traversal generator."""
|
"""Return providers traversal generator."""
|
||||||
yield from providers.traverse(*cls.providers.values(), types=types)
|
yield from providers.traverse(*cls.providers.values(), types=types)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __fetch_self(attributes):
|
||||||
|
self = None
|
||||||
|
alt_names = []
|
||||||
|
|
||||||
|
for name, value in attributes.items():
|
||||||
|
if not isinstance(value, providers.Self):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self is not None and value is not self:
|
||||||
|
raise errors.Error('Container can have only one "Self" provider')
|
||||||
|
|
||||||
|
if name != '__self__':
|
||||||
|
alt_names.append(name)
|
||||||
|
|
||||||
|
self = value
|
||||||
|
|
||||||
|
if self:
|
||||||
|
self.set_alt_names(alt_names)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(DeclarativeContainerMetaClass)
|
@six.add_metaclass(DeclarativeContainerMetaClass)
|
||||||
class DeclarativeContainer(Container):
|
class DeclarativeContainer(Container):
|
||||||
|
@ -448,9 +494,21 @@ class DeclarativeContainer(Container):
|
||||||
container = cls.instance_type()
|
container = cls.instance_type()
|
||||||
container.provider_type = cls.provider_type
|
container.provider_type = cls.provider_type
|
||||||
container.declarative_parent = cls
|
container.declarative_parent = cls
|
||||||
container.set_providers(**providers.deepcopy(cls.providers))
|
|
||||||
|
copied_providers = providers.deepcopy({ **cls.providers, **{'@@self@@': cls.__self__}})
|
||||||
|
copied_self = copied_providers.pop('@@self@@')
|
||||||
|
copied_self.set_container(container)
|
||||||
|
|
||||||
|
container.__self__ = copied_self
|
||||||
|
for name in copied_self.alt_names:
|
||||||
|
container.set_provider(name, copied_self)
|
||||||
|
|
||||||
|
for name, provider in copied_providers.items():
|
||||||
|
container.set_provider(name, provider)
|
||||||
|
|
||||||
container.override_providers(**overriding_providers)
|
container.override_providers(**overriding_providers)
|
||||||
container.apply_container_providers_overridings()
|
container.apply_container_providers_overridings()
|
||||||
|
|
||||||
return container
|
return container
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,6 +27,11 @@ cdef class Object(Provider):
|
||||||
cpdef object _provide(self, tuple args, dict kwargs)
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Self(Provider):
|
||||||
|
cdef object __container
|
||||||
|
cdef tuple __alt_names
|
||||||
|
|
||||||
|
|
||||||
cdef class Delegate(Provider):
|
cdef class Delegate(Provider):
|
||||||
cdef object __provides
|
cdef object __provides
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class Provider(Generic[T]):
|
||||||
def is_async_mode_undefined(self) -> bool: ...
|
def is_async_mode_undefined(self) -> bool: ...
|
||||||
@property
|
@property
|
||||||
def related(self) -> _Iterator[Provider]: ...
|
def related(self) -> _Iterator[Provider]: ...
|
||||||
def traverse(self, types: Optional[_Iterable[TT]] = None) -> _Iterator[TT]: ...
|
def traverse(self, types: Optional[_Iterable[Type[TT]]] = None) -> _Iterator[TT]: ...
|
||||||
def _copy_overridings(self, copied: Provider, memo: Optional[_Dict[Any, Any]]) -> None: ...
|
def _copy_overridings(self, copied: Provider, memo: Optional[_Dict[Any, Any]]) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,6 +85,14 @@ class Object(Provider[T]):
|
||||||
def __init__(self, provides: T) -> None: ...
|
def __init__(self, provides: T) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
|
class Self(Provider[T]):
|
||||||
|
def __init__(self, container: Optional[T] = None) -> None: ...
|
||||||
|
def set_container(self, container: T) -> None: ...
|
||||||
|
def set_alt_names(self, alt_names: _Iterable[Any]) -> None: ...
|
||||||
|
@property
|
||||||
|
def alt_names(self) -> Tuple[Any]: ...
|
||||||
|
|
||||||
|
|
||||||
class Delegate(Provider[Provider]):
|
class Delegate(Provider[Provider]):
|
||||||
def __init__(self, provides: Provider) -> None: ...
|
def __init__(self, provides: Provider) -> None: ...
|
||||||
@property
|
@property
|
||||||
|
@ -346,7 +354,7 @@ class Resource(Provider[T]):
|
||||||
|
|
||||||
|
|
||||||
class Container(Provider[T]):
|
class Container(Provider[T]):
|
||||||
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: Union[Provider, Any]) -> None: ...
|
||||||
def __getattr__(self, name: str) -> Provider: ...
|
def __getattr__(self, name: str) -> Provider: ...
|
||||||
@property
|
@property
|
||||||
def container(self) -> T: ...
|
def container(self) -> T: ...
|
||||||
|
|
|
@ -458,6 +458,57 @@ cdef class Object(Provider):
|
||||||
return self.__provides
|
return self.__provides
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Self(Provider):
|
||||||
|
"""Self provider returns own container."""
|
||||||
|
|
||||||
|
def __init__(self, container=None):
|
||||||
|
"""Initialize provider."""
|
||||||
|
self.__container = container
|
||||||
|
self.__alt_names = tuple()
|
||||||
|
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
|
||||||
|
|
||||||
|
copied = self.__class__()
|
||||||
|
copied.set_container(deepcopy(self.__container, memo))
|
||||||
|
copied.set_alt_names(self.__alt_names)
|
||||||
|
|
||||||
|
self._copy_overridings(copied, memo)
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return represent_provider(provider=self, provides=self.__container)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def set_container(self, container):
|
||||||
|
self.__container = container
|
||||||
|
|
||||||
|
def set_alt_names(self, alt_names):
|
||||||
|
self.__alt_names = tuple(set(alt_names))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alt_names(self):
|
||||||
|
return self.__alt_names
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs):
|
||||||
|
return self.__container
|
||||||
|
|
||||||
|
|
||||||
cdef class Delegate(Provider):
|
cdef class Delegate(Provider):
|
||||||
"""Delegate provider returns provider "as is".
|
"""Delegate provider returns provider "as is".
|
||||||
|
|
||||||
|
|
|
@ -335,3 +335,204 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
self.assertIs(obj31, obj41)
|
self.assertIs(obj31, obj41)
|
||||||
self.assertIs(obj32, obj42)
|
self.assertIs(obj32, obj42)
|
||||||
self.assertIs(obj33, obj43)
|
self.assertIs(obj33, obj43)
|
||||||
|
|
||||||
|
|
||||||
|
class SelfTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_self(self):
|
||||||
|
def call_bar(container):
|
||||||
|
return container.bar()
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = providers.Callable(call_bar, __self__)
|
||||||
|
bar = providers.Object('hello')
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.foo(), 'hello')
|
||||||
|
|
||||||
|
def test_self_attribute_implicit(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
pass
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__(), container)
|
||||||
|
|
||||||
|
def test_self_attribute_explicit(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__(), container)
|
||||||
|
|
||||||
|
def test_single_self(self):
|
||||||
|
with self.assertRaises(errors.Error):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
self1 = providers.Self()
|
||||||
|
self2 = providers.Self()
|
||||||
|
|
||||||
|
def test_self_attribute_alt_name_implicit(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
foo = providers.Self()
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__, container.foo)
|
||||||
|
self.assertEqual(set(container.__self__.alt_names), {'foo'})
|
||||||
|
|
||||||
|
def test_self_attribute_alt_name_explicit_1(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = __self__
|
||||||
|
bar = __self__
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__, container.foo)
|
||||||
|
self.assertIs(container.__self__, container.bar)
|
||||||
|
self.assertEqual(set(container.__self__.alt_names), {'foo', 'bar'})
|
||||||
|
|
||||||
|
def test_self_attribute_alt_name_explicit_2(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
foo = providers.Self()
|
||||||
|
bar = foo
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__, container.foo)
|
||||||
|
self.assertIs(container.__self__, container.bar)
|
||||||
|
self.assertEqual(set(container.__self__.alt_names), {'foo', 'bar'})
|
||||||
|
|
||||||
|
def test_providers_attribute_1(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = __self__
|
||||||
|
bar = __self__
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertEqual(container.providers, {})
|
||||||
|
self.assertEqual(Container.providers, {})
|
||||||
|
|
||||||
|
def test_providers_attribute_2(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
foo = providers.Self()
|
||||||
|
bar = foo
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertEqual(container.providers, {})
|
||||||
|
self.assertEqual(Container.providers, {})
|
||||||
|
|
||||||
|
def test_container_multiple_instances(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
|
||||||
|
container1 = Container()
|
||||||
|
container2 = Container()
|
||||||
|
|
||||||
|
self.assertIsNot(container1, container2)
|
||||||
|
self.assertIs(container1.__self__(), container1)
|
||||||
|
self.assertIs(container2.__self__(), container2)
|
||||||
|
|
||||||
|
def test_deepcopy(self):
|
||||||
|
def call_bar(container):
|
||||||
|
return container.bar()
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = providers.Callable(call_bar, __self__)
|
||||||
|
bar = providers.Object('hello')
|
||||||
|
|
||||||
|
container1 = Container()
|
||||||
|
container2 = providers.deepcopy(container1)
|
||||||
|
container1.bar.override('bye')
|
||||||
|
|
||||||
|
self.assertIs(container1.foo(), 'bye')
|
||||||
|
self.assertIs(container2.foo(), 'hello')
|
||||||
|
|
||||||
|
def test_deepcopy_alt_names_1(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = __self__
|
||||||
|
bar = foo
|
||||||
|
|
||||||
|
container1 = Container()
|
||||||
|
container2 = providers.deepcopy(container1)
|
||||||
|
|
||||||
|
self.assertIs(container2.__self__(), container2)
|
||||||
|
self.assertIs(container2.foo(), container2)
|
||||||
|
self.assertIs(container2.bar(), container2)
|
||||||
|
|
||||||
|
def test_deepcopy_alt_names_2(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
self = providers.Self()
|
||||||
|
|
||||||
|
container1 = Container()
|
||||||
|
container2 = providers.deepcopy(container1)
|
||||||
|
|
||||||
|
self.assertIs(container2.__self__(), container2)
|
||||||
|
self.assertIs(container2.self(), container2)
|
||||||
|
|
||||||
|
def test_deepcopy_no_self_dependencies(self):
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
|
||||||
|
container1 = Container()
|
||||||
|
container2 = providers.deepcopy(container1)
|
||||||
|
|
||||||
|
self.assertIsNot(container1, container2)
|
||||||
|
self.assertIsNot(container1.__self__, container2.__self__)
|
||||||
|
self.assertIs(container1.__self__(), container1)
|
||||||
|
self.assertIs(container2.__self__(), container2)
|
||||||
|
|
||||||
|
def test_with_container_provider(self):
|
||||||
|
def call_bar(container):
|
||||||
|
return container.bar()
|
||||||
|
|
||||||
|
class SubContainer(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = providers.Callable(call_bar, __self__)
|
||||||
|
bar = providers.Object('hello')
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
sub_container = providers.Container(SubContainer)
|
||||||
|
|
||||||
|
baz = providers.Callable(lambda value: value, sub_container.foo)
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.baz(), 'hello')
|
||||||
|
|
||||||
|
def test_with_container_provider_overriding(self):
|
||||||
|
def call_bar(container):
|
||||||
|
return container.bar()
|
||||||
|
|
||||||
|
class SubContainer(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
foo = providers.Callable(call_bar, __self__)
|
||||||
|
bar = providers.Object('hello')
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
sub_container = providers.Container(SubContainer, bar='bye')
|
||||||
|
|
||||||
|
baz = providers.Callable(lambda value: value, sub_container.foo)
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.baz(), 'bye')
|
||||||
|
|
||||||
|
def test_with_container_provider_self(self):
|
||||||
|
class SubContainer(containers.DeclarativeContainer):
|
||||||
|
__self__ = providers.Self()
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
sub_container = providers.Container(SubContainer)
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
self.assertIs(container.__self__(), container)
|
||||||
|
self.assertIs(container.sub_container().__self__(), container.sub_container())
|
||||||
|
|
|
@ -218,6 +218,68 @@ class ObjectProviderTests(unittest.TestCase):
|
||||||
hex(id(provider))))
|
hex(id(provider))))
|
||||||
|
|
||||||
|
|
||||||
|
class SelfProviderTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_is_provider(self):
|
||||||
|
self.assertTrue(providers.is_provider(providers.Self()))
|
||||||
|
|
||||||
|
def test_call_object_provider(self):
|
||||||
|
container = containers.DeclarativeContainer()
|
||||||
|
self.assertIs(providers.Self(container)(), container)
|
||||||
|
|
||||||
|
def test_set_container(self):
|
||||||
|
container = containers.DeclarativeContainer()
|
||||||
|
provider = providers.Self()
|
||||||
|
provider.set_container(container)
|
||||||
|
self.assertIs(provider(), container)
|
||||||
|
|
||||||
|
def test_set_alt_names(self):
|
||||||
|
provider = providers.Self()
|
||||||
|
provider.set_alt_names({'foo', 'bar', 'baz'})
|
||||||
|
self.assertEqual(set(provider.alt_names), {'foo', 'bar', 'baz'})
|
||||||
|
|
||||||
|
def test_deepcopy(self):
|
||||||
|
provider = providers.Self()
|
||||||
|
|
||||||
|
provider_copy = providers.deepcopy(provider)
|
||||||
|
|
||||||
|
self.assertIsNot(provider, provider_copy)
|
||||||
|
self.assertIsInstance(provider, providers.Self)
|
||||||
|
|
||||||
|
def test_deepcopy_from_memo(self):
|
||||||
|
provider = providers.Self()
|
||||||
|
provider_copy_memo = providers.Provider()
|
||||||
|
|
||||||
|
provider_copy = providers.deepcopy(
|
||||||
|
provider, memo={id(provider): provider_copy_memo})
|
||||||
|
|
||||||
|
self.assertIs(provider_copy, provider_copy_memo)
|
||||||
|
|
||||||
|
def test_deepcopy_overridden(self):
|
||||||
|
provider = providers.Self()
|
||||||
|
overriding_provider = providers.Provider()
|
||||||
|
|
||||||
|
provider.override(overriding_provider)
|
||||||
|
|
||||||
|
provider_copy = providers.deepcopy(provider)
|
||||||
|
overriding_provider_copy = provider_copy.overridden[0]
|
||||||
|
|
||||||
|
self.assertIsNot(provider, provider_copy)
|
||||||
|
self.assertIsInstance(provider, providers.Self)
|
||||||
|
|
||||||
|
self.assertIsNot(overriding_provider, overriding_provider_copy)
|
||||||
|
self.assertIsInstance(overriding_provider_copy, providers.Provider)
|
||||||
|
|
||||||
|
def test_repr(self):
|
||||||
|
container = containers.DeclarativeContainer()
|
||||||
|
provider = providers.Self(container)
|
||||||
|
self.assertEqual(repr(provider),
|
||||||
|
'<dependency_injector.providers.'
|
||||||
|
'Self({0}) at {1}>'.format(
|
||||||
|
repr(container),
|
||||||
|
hex(id(provider))))
|
||||||
|
|
||||||
|
|
||||||
class DelegateTests(unittest.TestCase):
|
class DelegateTests(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user