mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Container "self" injections (#392)
* Add implementation * Add Self provider tests * Add container tests * Remove ellipsis from tests to make them pass on Python 2 * Add tests * Add docs * Improve traverse() typing stubs * Update changelog
This commit is contained in:
parent
ce6d3df72c
commit
674a6b0f9e
|
@ -22,6 +22,7 @@ Containers module API docs - :py:mod:`dependency_injector.containers`.
|
|||
declarative
|
||||
dynamic
|
||||
specialization
|
||||
inject_self
|
||||
overriding
|
||||
reset_singletons
|
||||
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
|
||||
follows `Semantic versioning`_
|
||||
|
||||
Development version
|
||||
-------------------
|
||||
- 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
|
||||
------
|
||||
- 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)
|
File diff suppressed because it is too large
Load Diff
|
@ -7,15 +7,13 @@ from typing import (
|
|||
Union,
|
||||
ClassVar,
|
||||
Callable as _Callable,
|
||||
Sequence,
|
||||
Iterable,
|
||||
Iterator,
|
||||
TypeVar,
|
||||
Awaitable,
|
||||
overload,
|
||||
)
|
||||
|
||||
from .providers import Provider
|
||||
from .providers import Provider, Self
|
||||
|
||||
|
||||
C_Base = TypeVar('C_Base', bound='Container')
|
||||
|
@ -29,12 +27,13 @@ class Container:
|
|||
providers: Dict[str, Provider]
|
||||
dependencies: Dict[str, Provider]
|
||||
overridden: Tuple[Provider]
|
||||
__self__: Provider
|
||||
__self__: Self
|
||||
def __init__(self) -> None: ...
|
||||
def __deepcopy__(self, memo: Optional[Dict[str, Any]]) -> Provider: ...
|
||||
def __setattr__(self, name: str, value: Union[Provider, Any]) -> None: ...
|
||||
def __delattr__(self, name: str) -> None: ...
|
||||
def set_providers(self, **providers: Provider): ...
|
||||
def set_provider(self, name: str, provider: Provider) -> None: ...
|
||||
def override(self, overriding: C_Base) -> None: ...
|
||||
def override_providers(self, **overriding_providers: Provider) -> None: ...
|
||||
def reset_last_overriding(self) -> None: ...
|
||||
|
@ -47,10 +46,10 @@ class Container:
|
|||
def apply_container_providers_overridings(self) -> None: ...
|
||||
def reset_singletons(self) -> None: ...
|
||||
@overload
|
||||
def traverse(self, types: Optional[Sequence[TT]] = None) -> Iterator[TT]: ...
|
||||
def traverse(self, types: Optional[Iterable[Type[TT]]] = None) -> _Iterator[TT]: ...
|
||||
@classmethod
|
||||
@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): ...
|
||||
|
|
|
@ -69,7 +69,7 @@ class DynamicContainer(Container):
|
|||
self.declarative_parent = None
|
||||
self.wired_to_modules = []
|
||||
self.wired_to_packages = []
|
||||
self.__self__ = providers.Object(self)
|
||||
self.__self__ = providers.Self(self)
|
||||
super(DynamicContainer, self).__init__()
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
@ -79,12 +79,18 @@ class DynamicContainer(Container):
|
|||
return copied
|
||||
|
||||
copied = self.__class__()
|
||||
memo[id(self)] = copied
|
||||
|
||||
copied.provider_type = providers.Provider
|
||||
copied.overridden = providers.deepcopy(self.overridden, memo)
|
||||
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():
|
||||
setattr(copied, name, provider)
|
||||
copied.set_provider(name, provider)
|
||||
|
||||
return copied
|
||||
|
||||
|
@ -102,7 +108,7 @@ class DynamicContainer(Container):
|
|||
|
||||
: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)
|
||||
self.providers[name] = value
|
||||
super(DynamicContainer, self).__setattr__(name, value)
|
||||
|
@ -154,6 +160,19 @@ class DynamicContainer(Container):
|
|||
for name, provider in six.iteritems(providers):
|
||||
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):
|
||||
"""Override current container by overriding container.
|
||||
|
||||
|
@ -282,6 +301,10 @@ class DeclarativeContainerMetaClass(type):
|
|||
|
||||
def __new__(type mcs, str class_name, tuple bases, dict attributes):
|
||||
"""Declarative container class factory."""
|
||||
self = mcs.__fetch_self(attributes)
|
||||
if self is None:
|
||||
self = providers.Self()
|
||||
|
||||
containers = {
|
||||
name: container
|
||||
for name, container in six.iteritems(attributes)
|
||||
|
@ -291,7 +314,7 @@ class DeclarativeContainerMetaClass(type):
|
|||
cls_providers = {
|
||||
name: provider
|
||||
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 = {
|
||||
|
@ -312,7 +335,8 @@ class DeclarativeContainerMetaClass(type):
|
|||
|
||||
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):
|
||||
_check_provider_type(cls, provider)
|
||||
|
@ -375,6 +399,28 @@ class DeclarativeContainerMetaClass(type):
|
|||
"""Return providers traversal generator."""
|
||||
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)
|
||||
class DeclarativeContainer(Container):
|
||||
|
@ -448,9 +494,21 @@ class DeclarativeContainer(Container):
|
|||
container = cls.instance_type()
|
||||
container.provider_type = cls.provider_type
|
||||
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.apply_container_providers_overridings()
|
||||
|
||||
return container
|
||||
|
||||
@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)
|
||||
|
||||
|
||||
cdef class Self(Provider):
|
||||
cdef object __container
|
||||
cdef tuple __alt_names
|
||||
|
||||
|
||||
cdef class Delegate(Provider):
|
||||
cdef object __provides
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class Provider(Generic[T]):
|
|||
def is_async_mode_undefined(self) -> bool: ...
|
||||
@property
|
||||
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: ...
|
||||
|
||||
|
||||
|
@ -85,6 +85,14 @@ class Object(Provider[T]):
|
|||
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]):
|
||||
def __init__(self, provides: Provider) -> None: ...
|
||||
@property
|
||||
|
@ -346,7 +354,7 @@ class Resource(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: ...
|
||||
@property
|
||||
def container(self) -> T: ...
|
||||
|
|
|
@ -458,6 +458,57 @@ cdef class Object(Provider):
|
|||
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):
|
||||
"""Delegate provider returns provider "as is".
|
||||
|
||||
|
|
|
@ -335,3 +335,204 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
|||
self.assertIs(obj31, obj41)
|
||||
self.assertIs(obj32, obj42)
|
||||
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))))
|
||||
|
||||
|
||||
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):
|
||||
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user