mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-28 12:33:59 +03:00
Add with support for container.override_providers() (#517)
* Add implementation, tests, and typing stub * Update documentation * Update changelog
This commit is contained in:
parent
73a43e6191
commit
284dee6e58
|
@ -34,10 +34,39 @@ Injections in the declarative container are done the usual way:
|
|||
:language: python
|
||||
:lines: 3-
|
||||
|
||||
You can override the container providers when you create the container instance:
|
||||
You can override container providers while creating a container instance:
|
||||
|
||||
.. literalinclude:: ../../examples/containers/declarative_override_providers.py
|
||||
:language: python
|
||||
:lines: 3-
|
||||
:emphasize-lines: 13
|
||||
|
||||
Alternatively, you can call ``container.override_providers()`` method when the container instance
|
||||
already exists:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 3
|
||||
|
||||
container = Container()
|
||||
|
||||
container.override_providers(foo=mock.Mock(Foo), bar=mock.Mock(Bar))
|
||||
|
||||
assert isinstance(container.foo(), mock.Mock)
|
||||
assert isinstance(container.bar(), mock.Mock)
|
||||
|
||||
You can also use ``container.override_providers()`` with a context manager to reset
|
||||
provided overriding after the context is closed:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 3
|
||||
|
||||
container = Container()
|
||||
|
||||
with container.override_providers(foo=mock.Mock(Foo), bar=mock.Mock(Bar)):
|
||||
assert isinstance(container.foo(), mock.Mock)
|
||||
assert isinstance(container.bar(), mock.Mock)
|
||||
|
||||
assert isinstance(container.foo(), Foo)
|
||||
assert isinstance(container.bar(), Bar)
|
||||
|
||||
.. disqus::
|
||||
|
|
|
@ -12,6 +12,7 @@ Develop
|
|||
- Improve wiring with adding importing modules and packages from a string
|
||||
``container.wire(modules=["yourapp.module1"])``.
|
||||
- Add container wiring configuration ``wiring_config = containers.WiringConfiguration()``.
|
||||
- Add support of ``with`` statement for ``container.override_providers()`` method.
|
||||
- Update documentation and fix typos.
|
||||
|
||||
4.36.2
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -50,7 +50,7 @@ class Container:
|
|||
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: Union[Provider, Any]) -> None: ...
|
||||
def override_providers(self, **overriding_providers: Union[Provider, Any]) -> ProvidersOverridingContext[C_Base]: ...
|
||||
def reset_last_overriding(self) -> None: ...
|
||||
def reset_override(self) -> None: ...
|
||||
def is_auto_wiring_enabled(self) -> bool: ...
|
||||
|
@ -90,6 +90,12 @@ class DeclarativeContainer(Container):
|
|||
def __init__(self, **overriding_providers: Union[Provider, Any]) -> None: ...
|
||||
|
||||
|
||||
class ProvidersOverridingContext(Generic[T]):
|
||||
def __init__(self, container: T, overridden_providers: Iterable[Union[Provider, Any]]) -> None: ...
|
||||
def __enter__(self) -> T: ...
|
||||
def __exit__(self, *_: Any) -> None: ...
|
||||
|
||||
|
||||
class SingletonResetContext(Generic[T]):
|
||||
def __init__(self, container: T): ...
|
||||
def __enter__(self) -> T: ...
|
||||
|
|
|
@ -240,9 +240,12 @@ class DynamicContainer(Container):
|
|||
|
||||
:rtype: None
|
||||
"""
|
||||
overridden_providers = []
|
||||
for name, overriding_provider in six.iteritems(overriding_providers):
|
||||
container_provider = getattr(self, name)
|
||||
container_provider.override(overriding_provider)
|
||||
overridden_providers.append(container_provider)
|
||||
return ProvidersOverridingContext(self, overridden_providers)
|
||||
|
||||
def reset_last_overriding(self):
|
||||
"""Reset last overriding provider for each container providers.
|
||||
|
@ -784,6 +787,21 @@ class SingletonResetContext:
|
|||
self._container.reset_singletons()
|
||||
|
||||
|
||||
|
||||
class ProvidersOverridingContext:
|
||||
|
||||
def __init__(self, container, overridden_providers):
|
||||
self._container = container
|
||||
self._overridden_providers = overridden_providers
|
||||
|
||||
def __enter__(self):
|
||||
return self._container
|
||||
|
||||
def __exit__(self, *_):
|
||||
for provider in self._overridden_providers:
|
||||
provider.reset_last_overriding()
|
||||
|
||||
|
||||
def override(object container):
|
||||
""":py:class:`DeclarativeContainer` overriding decorator.
|
||||
|
||||
|
|
|
@ -58,9 +58,11 @@ class Container6(containers.DeclarativeContainer):
|
|||
container6: containers.Container = Container6()
|
||||
|
||||
|
||||
# Test 7: to override()
|
||||
# Test 7: to override_providers()
|
||||
class Container7(containers.DeclarativeContainer):
|
||||
provider = providers.Factory(str)
|
||||
|
||||
container7 = Container7()
|
||||
container7.override_providers(provider="new_value")
|
||||
with container7.override_providers(a=providers.Provider()):
|
||||
...
|
||||
|
|
|
@ -14,6 +14,8 @@ container2.override(containers.DynamicContainer())
|
|||
# Test 3: to check override_providers()
|
||||
container3 = containers.DynamicContainer()
|
||||
container3.override_providers(a=providers.Provider())
|
||||
with container3.override_providers(a=providers.Provider()):
|
||||
...
|
||||
|
||||
# Test 4: to check set_providers()
|
||||
container4 = containers.DynamicContainer()
|
||||
|
|
|
@ -134,6 +134,19 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
|||
self.assertIs(container_a.p11.last_overriding, p1)
|
||||
self.assertIs(container_a.p12.last_overriding, p2)
|
||||
|
||||
def test_override_providers_context_manager(self):
|
||||
p1 = providers.Provider()
|
||||
p2 = providers.Provider()
|
||||
container_a = ContainerA()
|
||||
|
||||
with container_a.override_providers(p11=p1, p12=p2) as container:
|
||||
self.assertIs(container, container_a)
|
||||
self.assertIs(container_a.p11.last_overriding, p1)
|
||||
self.assertIs(container_a.p12.last_overriding, p2)
|
||||
|
||||
self.assertIsNone(container_a.p11.last_overriding)
|
||||
self.assertIsNone(container_a.p12.last_overriding)
|
||||
|
||||
def test_override_providers_with_unknown_provider(self):
|
||||
container_a = ContainerA()
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user