mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 16:07:51 +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 |    :language: python | ||||||
|    :lines: 3- |    :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 | .. literalinclude:: ../../examples/containers/declarative_override_providers.py | ||||||
|    :language: python |    :language: python | ||||||
|    :lines: 3- |    :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:: | .. disqus:: | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ Develop | ||||||
| - Improve wiring with adding importing modules and packages from a string | - Improve wiring with adding importing modules and packages from a string | ||||||
|   ``container.wire(modules=["yourapp.module1"])``. |   ``container.wire(modules=["yourapp.module1"])``. | ||||||
| - Add container wiring configuration ``wiring_config = containers.WiringConfiguration()``. | - Add container wiring configuration ``wiring_config = containers.WiringConfiguration()``. | ||||||
|  | - Add support of ``with`` statement for ``container.override_providers()`` method. | ||||||
| - Update documentation and fix typos. | - Update documentation and fix typos. | ||||||
| 
 | 
 | ||||||
| 4.36.2 | 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_providers(self, **providers: Provider): ... | ||||||
|     def set_provider(self, name: str, provider: Provider) -> None: ... |     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: Union[Provider, Any]) -> None: ... |     def override_providers(self, **overriding_providers: Union[Provider, Any]) -> ProvidersOverridingContext[C_Base]: ... | ||||||
|     def reset_last_overriding(self) -> None: ... |     def reset_last_overriding(self) -> None: ... | ||||||
|     def reset_override(self) -> None: ... |     def reset_override(self) -> None: ... | ||||||
|     def is_auto_wiring_enabled(self) -> bool: ... |     def is_auto_wiring_enabled(self) -> bool: ... | ||||||
|  | @ -90,6 +90,12 @@ class DeclarativeContainer(Container): | ||||||
|     def __init__(self, **overriding_providers: Union[Provider, Any]) -> None: ... |     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]): | class SingletonResetContext(Generic[T]): | ||||||
|     def __init__(self, container: T): ... |     def __init__(self, container: T): ... | ||||||
|     def __enter__(self) -> T: ... |     def __enter__(self) -> T: ... | ||||||
|  |  | ||||||
|  | @ -240,9 +240,12 @@ class DynamicContainer(Container): | ||||||
| 
 | 
 | ||||||
|         :rtype: None |         :rtype: None | ||||||
|         """ |         """ | ||||||
|  |         overridden_providers = [] | ||||||
|         for name, overriding_provider in six.iteritems(overriding_providers): |         for name, overriding_provider in six.iteritems(overriding_providers): | ||||||
|             container_provider = getattr(self, name) |             container_provider = getattr(self, name) | ||||||
|             container_provider.override(overriding_provider) |             container_provider.override(overriding_provider) | ||||||
|  |             overridden_providers.append(container_provider) | ||||||
|  |         return ProvidersOverridingContext(self, overridden_providers) | ||||||
| 
 | 
 | ||||||
|     def reset_last_overriding(self): |     def reset_last_overriding(self): | ||||||
|         """Reset last overriding provider for each container providers. |         """Reset last overriding provider for each container providers. | ||||||
|  | @ -784,6 +787,21 @@ class SingletonResetContext: | ||||||
|         self._container.reset_singletons() |         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): | def override(object container): | ||||||
|     """:py:class:`DeclarativeContainer` overriding decorator. |     """:py:class:`DeclarativeContainer` overriding decorator. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -58,9 +58,11 @@ class Container6(containers.DeclarativeContainer): | ||||||
| container6: containers.Container = Container6() | container6: containers.Container = Container6() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Test 7: to override() | # Test 7: to override_providers() | ||||||
| class Container7(containers.DeclarativeContainer): | class Container7(containers.DeclarativeContainer): | ||||||
|     provider = providers.Factory(str) |     provider = providers.Factory(str) | ||||||
| 
 | 
 | ||||||
| container7 = Container7() | container7 = Container7() | ||||||
| container7.override_providers(provider="new_value") | 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() | # Test 3: to check override_providers() | ||||||
| container3 = containers.DynamicContainer() | container3 = containers.DynamicContainer() | ||||||
| container3.override_providers(a=providers.Provider()) | container3.override_providers(a=providers.Provider()) | ||||||
|  | with container3.override_providers(a=providers.Provider()): | ||||||
|  |     ... | ||||||
| 
 | 
 | ||||||
| # Test 4: to check set_providers() | # Test 4: to check set_providers() | ||||||
| container4 = containers.DynamicContainer() | container4 = containers.DynamicContainer() | ||||||
|  |  | ||||||
|  | @ -134,6 +134,19 @@ class DeclarativeContainerInstanceTests(unittest.TestCase): | ||||||
|         self.assertIs(container_a.p11.last_overriding, p1) |         self.assertIs(container_a.p11.last_overriding, p1) | ||||||
|         self.assertIs(container_a.p12.last_overriding, p2) |         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): |     def test_override_providers_with_unknown_provider(self): | ||||||
|         container_a = ContainerA() |         container_a = ContainerA() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user