367 Fix declarative container metaclass bug with child providers

This commit is contained in:
Roman Mogylatov 2021-01-29 16:37:50 -05:00
parent f188811d87
commit 39cb963351
5 changed files with 2181 additions and 11007 deletions

View File

@ -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
-------------------
- Fix declarative container metaclass bug: parent container providers replaced child container providers.
See issue: `#367 <https://github.com/ets-labs/python-dependency-injector/issues/367>`_.
Many thanks to `Shaun Cutts <https://github.com/shaunc>`_ for finding and report the issue.
4.13.0
------
- Add ``default`` argument to the dependency provider: ``Dependency(..., default=...)``.

File diff suppressed because it is too large Load Diff

View File

@ -284,34 +284,33 @@ class DeclarativeContainerMetaClass(type):
def __new__(type mcs, str class_name, tuple bases, dict attributes):
"""Declarative container class factory."""
cdef tuple cls_providers
cdef tuple inherited_providers
cdef type cls
containers = tuple(
(name, container)
containers = {
name: container
for name, container in six.iteritems(attributes)
if is_container(container)
)
}
attributes['containers'] = dict(containers)
cls_providers = tuple(
(name, provider)
cls_providers = {
name: provider
for name, provider in six.iteritems(attributes)
if isinstance(provider, Provider)
)
}
inherited_providers = tuple(
(name, provider)
inherited_providers = {
name: provider
for base in bases
if is_container(base) and base is not DynamicContainer
for name, provider in six.iteritems(base.providers)
)
}
attributes['cls_providers'] = dict(cls_providers)
attributes['inherited_providers'] = dict(inherited_providers)
attributes['providers'] = dict(cls_providers + inherited_providers)
providers = {}
providers.update(inherited_providers)
providers.update(cls_providers)
attributes['containers'] = containers
attributes['inherited_providers'] = inherited_providers
attributes['cls_providers'] = cls_providers
attributes['providers'] = providers
cls = <type>type.__new__(mcs, class_name, bases, attributes)

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,29 @@ class DeclarativeContainerTests(unittest.TestCase):
p31=ContainerC.p31,
p32=ContainerC.p32))
def test_providers_attribute_with_redefinition(self):
p1 = providers.Provider()
p2 = providers.Provider()
class ContainerA2(ContainerA):
p11 = p1
p12 = p2
self.assertEqual(
ContainerA.providers,
{
'p11': ContainerA.p11,
'p12': ContainerA.p12,
},
)
self.assertEqual(
ContainerA2.providers,
{
'p11': p1,
'p12': p2,
},
)
def test_cls_providers_attribute(self):
self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11,
p12=ContainerA.p12))