mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 01:26:51 +03:00
Add dependencies attribute to declarative and dynamic containers (#359)
* Add .dependencies attribute to declarative and dynamic containers * Update changelog * Add typing tests
This commit is contained in:
parent
3e207a4f21
commit
907a4f1887
|
@ -7,6 +7,13 @@ that were made in every particular version.
|
|||
From version 0.7.6 *Dependency Injector* framework strictly
|
||||
follows `Semantic versioning`_
|
||||
|
||||
Development version
|
||||
-------------------
|
||||
- Add ``.dependencies`` attribute to the ``DeclarativeContainer`` and ``DynamicContainer``.
|
||||
It returns dictionary of container ``Dependency`` and ``DependenciesContainer`` providers.
|
||||
See issue `#357 <https://github.com/ets-labs/python-dependency-injector/issues/357>`_.
|
||||
Many thanks to `Shaun Cutts <https://github.com/shaunc>`_ for suggesting the feature.
|
||||
|
||||
4.8.3
|
||||
-----
|
||||
- Fix a bug in the ``Configuration`` provider to correctly handle overriding by ``None``.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,6 +24,7 @@ C_Overriding = TypeVar('C_Overriding', bound='DeclarativeContainer')
|
|||
class Container:
|
||||
provider_type: Type[Provider] = Provider
|
||||
providers: Dict[str, Provider]
|
||||
dependencies: Dict[str, Provider]
|
||||
overridden: Tuple[Provider]
|
||||
__self__: Provider
|
||||
def __init__(self) -> None: ...
|
||||
|
|
|
@ -15,6 +15,8 @@ from .providers cimport (
|
|||
Provider,
|
||||
Object,
|
||||
Resource,
|
||||
Dependency,
|
||||
DependenciesContainer,
|
||||
Container as ContainerProvider,
|
||||
deepcopy,
|
||||
)
|
||||
|
@ -125,6 +127,22 @@ class DynamicContainer(object):
|
|||
del self.providers[name]
|
||||
super(DynamicContainer, self).__delattr__(name)
|
||||
|
||||
@property
|
||||
def dependencies(self):
|
||||
"""Return dependency providers dictionary.
|
||||
|
||||
Dependency providers can be both of :py:class:`dependency_injector.providers.Dependency` and
|
||||
:py:class:`dependency_injector.providers.DependenciesContainer`.
|
||||
|
||||
:rtype:
|
||||
dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return {
|
||||
name: provider
|
||||
for name, provider in self.providers.items()
|
||||
if isinstance(provider, (Dependency, DependenciesContainer))
|
||||
}
|
||||
|
||||
def set_providers(self, **providers):
|
||||
"""Set container providers.
|
||||
|
||||
|
@ -340,6 +358,22 @@ class DeclarativeContainerMetaClass(type):
|
|||
del cls.cls_providers[name]
|
||||
super(DeclarativeContainerMetaClass, cls).__delattr__(name)
|
||||
|
||||
@property
|
||||
def dependencies(cls):
|
||||
"""Return dependency providers dictionary.
|
||||
|
||||
Dependency providers can be both of :py:class:`dependency_injector.providers.Dependency` and
|
||||
:py:class:`dependency_injector.providers.DependenciesContainer`.
|
||||
|
||||
:rtype:
|
||||
dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return {
|
||||
name: provider
|
||||
for name, provider in cls.providers.items()
|
||||
if isinstance(provider, (Dependency, DependenciesContainer))
|
||||
}
|
||||
|
||||
|
||||
@six.add_metaclass(DeclarativeContainerMetaClass)
|
||||
class DeclarativeContainer(object):
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Dict
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
|
@ -38,3 +40,11 @@ class Container4(containers.DeclarativeContainer):
|
|||
|
||||
container4 = Container4()
|
||||
container4.override(Container4())
|
||||
|
||||
|
||||
# Test 5: to check .dependencies attribute
|
||||
class Container5(containers.DeclarativeContainer):
|
||||
provider = providers.Factory(int)
|
||||
|
||||
|
||||
dependencies: Dict[str, providers.Provider] = Container5.dependencies
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Dict
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
|
@ -16,3 +18,7 @@ container3.override_providers(a=providers.Provider())
|
|||
# Test 4: to check set_providers()
|
||||
container4 = containers.DynamicContainer()
|
||||
container4.set_providers(a=providers.Provider())
|
||||
|
||||
# Test 5: to check .dependencies attribute
|
||||
container5 = containers.DynamicContainer()
|
||||
dependencies: Dict[str, providers.Provider] = container5.dependencies
|
||||
|
|
|
@ -60,6 +60,32 @@ class DeclarativeContainerTests(unittest.TestCase):
|
|||
p21=ContainerB.p21,
|
||||
p22=ContainerB.p22))
|
||||
|
||||
def test_dependencies_attribute(self):
|
||||
class ContainerD(ContainerC):
|
||||
p41 = providers.Dependency()
|
||||
p42 = providers.DependenciesContainer()
|
||||
|
||||
class ContainerE(ContainerD):
|
||||
p51 = providers.Dependency()
|
||||
p52 = providers.DependenciesContainer()
|
||||
|
||||
self.assertEqual(
|
||||
ContainerD.dependencies,
|
||||
{
|
||||
'p41': ContainerD.p41,
|
||||
'p42': ContainerD.p42,
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
ContainerE.dependencies,
|
||||
{
|
||||
'p41': ContainerD.p41,
|
||||
'p42': ContainerD.p42,
|
||||
'p51': ContainerE.p51,
|
||||
'p52': ContainerE.p52,
|
||||
},
|
||||
)
|
||||
|
||||
def test_set_get_del_providers(self):
|
||||
a_p13 = providers.Provider()
|
||||
b_p23 = providers.Provider()
|
||||
|
|
|
@ -24,6 +24,12 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
|||
self.assertIsNot(container_a1.p12, container_a2.p12)
|
||||
self.assertNotEqual(container_a1.providers, container_a2.providers)
|
||||
|
||||
def test_dependencies_attribute(self):
|
||||
container = ContainerA()
|
||||
container.a1 = providers.Dependency()
|
||||
container.a2 = providers.DependenciesContainer()
|
||||
self.assertEqual(container.dependencies, {'a1': container.a1, 'a2': container.a2})
|
||||
|
||||
def test_set_get_del_providers(self):
|
||||
p13 = providers.Provider()
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user