mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-28 17:50:35 +03:00
Merge branch 'release/4.35.3' into master
This commit is contained in:
commit
48df949cd5
|
@ -7,6 +7,13 @@ that were made in every particular version.
|
|||
From version 0.7.6 *Dependency Injector* framework strictly
|
||||
follows `Semantic versioning`_
|
||||
|
||||
4.35.3
|
||||
------
|
||||
- Fix ``@containers.copy()`` decorator to respect dependencies on parent providers.
|
||||
See issue `#477 <https://github.com/ets-labs/python-dependency-injector/issues/477>`_.
|
||||
Thanks to `Andrey Torsunov @gtors <https://github.com/gtors>`_ for reporting the issue.
|
||||
- Fix typing stub for ``container.override_providers()`` to accept other types besides ``Provider``.
|
||||
|
||||
4.35.2
|
||||
------
|
||||
- Update wiring to support modules provided as packages.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Top-level package."""
|
||||
|
||||
__version__ = '4.35.2'
|
||||
__version__ = '4.35.3'
|
||||
"""Version number.
|
||||
|
||||
:type: str
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,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: Provider) -> None: ...
|
||||
def override_providers(self, **overriding_providers: Union[Provider, Any]) -> None: ...
|
||||
def reset_last_overriding(self) -> None: ...
|
||||
def reset_override(self) -> None: ...
|
||||
def wire(self, modules: Optional[Iterable[Any]] = None, packages: Optional[Iterable[Any]] = None) -> None: ...
|
||||
|
|
|
@ -733,43 +733,44 @@ def override(object container):
|
|||
return _decorator
|
||||
|
||||
|
||||
def copy(object container):
|
||||
def copy(object base_container):
|
||||
""":py:class:`DeclarativeContainer` copying decorator.
|
||||
|
||||
This decorator copies all providers from provided container to decorated one.
|
||||
If one of the decorated container providers matches to source container
|
||||
providers by name, it would be replaced by reference.
|
||||
|
||||
:param container: Container that should be copied by decorated container.
|
||||
:type container: :py:class:`DeclarativeContainer`
|
||||
:param base_container: Container that should be copied by decorated container.
|
||||
:type base_container: :py:class:`DeclarativeContainer`
|
||||
|
||||
:return: Declarative container's copying decorator.
|
||||
:rtype: callable(:py:class:`DeclarativeContainer`)
|
||||
"""
|
||||
def _get_providers_memo(from_providers, source_providers):
|
||||
memo = dict()
|
||||
|
||||
for name, provider in from_providers.items():
|
||||
try:
|
||||
source_provider = source_providers[name]
|
||||
except KeyError:
|
||||
def _get_memo_for_matching_names(new_providers, base_providers):
|
||||
memo = {}
|
||||
for new_provider_name, new_provider in six.iteritems(new_providers):
|
||||
if new_provider_name not in base_providers:
|
||||
continue
|
||||
else:
|
||||
memo[id(source_provider)] = provider
|
||||
source_provider = base_providers[new_provider_name]
|
||||
memo[id(source_provider)] = new_provider
|
||||
|
||||
if hasattr(provider, 'providers') and hasattr(source_provider, 'providers'):
|
||||
sub_memo = _get_providers_memo(provider.providers, source_provider.providers)
|
||||
memo.update(sub_memo)
|
||||
if hasattr(new_provider, 'providers') and hasattr(source_provider, 'providers'):
|
||||
sub_memo = _get_memo_for_matching_names(new_provider.providers, source_provider.providers)
|
||||
memo.update(sub_memo)
|
||||
return memo
|
||||
|
||||
def _decorator(copied_container):
|
||||
memo = _get_providers_memo(copied_container.cls_providers, container.providers)
|
||||
def _decorator(new_container):
|
||||
memo = {}
|
||||
memo.update(_get_memo_for_matching_names(new_container.cls_providers, base_container.providers))
|
||||
|
||||
providers_copy = providers.deepcopy(container.providers, memo)
|
||||
for name, provider in six.iteritems(providers_copy):
|
||||
setattr(copied_container, name, provider)
|
||||
new_providers = {}
|
||||
new_providers.update(providers.deepcopy(base_container.providers, memo))
|
||||
new_providers.update(providers.deepcopy(new_container.cls_providers, memo))
|
||||
|
||||
for name, provider in six.iteritems(new_providers):
|
||||
setattr(new_container, name, provider)
|
||||
return new_container
|
||||
|
||||
return copied_container
|
||||
return _decorator
|
||||
|
||||
|
||||
|
|
|
@ -56,3 +56,11 @@ class Container6(containers.DeclarativeContainer):
|
|||
|
||||
|
||||
container6: containers.Container = Container6()
|
||||
|
||||
|
||||
# Test 7: to override()
|
||||
class Container7(containers.DeclarativeContainer):
|
||||
provider = providers.Factory(str)
|
||||
|
||||
container7 = Container7()
|
||||
container7.override_providers(provider='new_value')
|
||||
|
|
|
@ -308,17 +308,31 @@ class DeclarativeContainerTests(unittest.TestCase):
|
|||
self.assertIsNot(_Container1.p11, _Container2.p11)
|
||||
self.assertIsNot(_Container1.p12, _Container2.p12)
|
||||
|
||||
self.assertIs(_Container.p12.kwargs['p11'], _Container.p11)
|
||||
self.assertIs(_Container1.p12.kwargs['p11'], _Container1.p11)
|
||||
self.assertIs(_Container2.p12.kwargs['p11'], _Container2.p11)
|
||||
|
||||
self.assertEqual(_Container.p12(), dict(p11=0))
|
||||
self.assertEqual(_Container1.p12(), dict(p11=1))
|
||||
self.assertEqual(_Container2.p12(), dict(p11=2))
|
||||
self.assertEqual(_Container.p12(), {'p11': 0})
|
||||
self.assertEqual(_Container1.p12(), {'p11': 1})
|
||||
self.assertEqual(_Container2.p12(), {'p11': 2})
|
||||
|
||||
self.assertEqual(_Container1.p13(), 11)
|
||||
self.assertEqual(_Container2.p13(), 22)
|
||||
|
||||
def test_copy_with_parent_dependency(self):
|
||||
# See: https://github.com/ets-labs/python-dependency-injector/issues/477
|
||||
class Base(containers.DeclarativeContainer):
|
||||
p11 = providers.Object(0)
|
||||
p12 = providers.Factory(dict, p11=p11)
|
||||
|
||||
@containers.copy(Base)
|
||||
class New(Base):
|
||||
p13 = providers.Factory(dict, p12=Base.p12)
|
||||
|
||||
new1 = New()
|
||||
new2 = New(p11=1)
|
||||
new3 = New(p11=2)
|
||||
|
||||
self.assertEqual(new1.p13(), {'p12': {'p11': 0}})
|
||||
self.assertEqual(new2.p13(), {'p12': {'p11': 1}})
|
||||
self.assertEqual(new3.p13(), {'p12': {'p11': 2}})
|
||||
|
||||
def test_copy_with_replacing_subcontainer_providers(self):
|
||||
# See: https://github.com/ets-labs/python-dependency-injector/issues/374
|
||||
class X(containers.DeclarativeContainer):
|
||||
|
|
Loading…
Reference in New Issue
Block a user