mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Add configuration provider
This commit is contained in:
parent
a79df278b5
commit
3f8e53aa9c
4
setup.py
4
setup.py
|
@ -51,6 +51,10 @@ setup(name='dependency-injector',
|
||||||
['src/dependency_injector/providers/base.c'],
|
['src/dependency_injector/providers/base.c'],
|
||||||
define_macros=defined_macros,
|
define_macros=defined_macros,
|
||||||
extra_compile_args=['-O2']),
|
extra_compile_args=['-O2']),
|
||||||
|
Extension('dependency_injector.providers.configuration',
|
||||||
|
['src/dependency_injector/providers/configuration.c'],
|
||||||
|
define_macros=defined_macros,
|
||||||
|
extra_compile_args=['-O2']),
|
||||||
Extension('dependency_injector.providers.callables',
|
Extension('dependency_injector.providers.callables',
|
||||||
['src/dependency_injector/providers/callables.c'],
|
['src/dependency_injector/providers/callables.c'],
|
||||||
define_macros=defined_macros,
|
define_macros=defined_macros,
|
||||||
|
|
|
@ -7,6 +7,9 @@ from .base import (
|
||||||
ExternalDependency,
|
ExternalDependency,
|
||||||
OverridingContext,
|
OverridingContext,
|
||||||
)
|
)
|
||||||
|
from .configuration import (
|
||||||
|
Configuration,
|
||||||
|
)
|
||||||
from .callables import (
|
from .callables import (
|
||||||
Callable,
|
Callable,
|
||||||
DelegatedCallable,
|
DelegatedCallable,
|
||||||
|
@ -48,6 +51,8 @@ __all__ = (
|
||||||
'ExternalDependency',
|
'ExternalDependency',
|
||||||
'OverridingContext',
|
'OverridingContext',
|
||||||
|
|
||||||
|
'Configuration',
|
||||||
|
|
||||||
'Callable',
|
'Callable',
|
||||||
'DelegatedCallable',
|
'DelegatedCallable',
|
||||||
|
|
||||||
|
|
4868
src/dependency_injector/providers/configuration.c
Normal file
4868
src/dependency_injector/providers/configuration.c
Normal file
File diff suppressed because it is too large
Load Diff
19
src/dependency_injector/providers/configuration.pxd
Normal file
19
src/dependency_injector/providers/configuration.pxd
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
"""Dependency injector configuration providers.
|
||||||
|
|
||||||
|
Powered by Cython.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .base cimport (
|
||||||
|
Provider,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Configuration(Provider):
|
||||||
|
cdef str __name
|
||||||
|
cdef object __value
|
||||||
|
cdef dict __children
|
||||||
|
|
||||||
|
cpdef str get_name(self)
|
||||||
|
cpdef object update(self, object value)
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
cpdef str _get_child_name(self, str child_name)
|
99
src/dependency_injector/providers/configuration.pyx
Normal file
99
src/dependency_injector/providers/configuration.pyx
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
"""Dependency injector configuration providers.
|
||||||
|
|
||||||
|
Powered by Cython.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .base cimport (
|
||||||
|
Provider,
|
||||||
|
)
|
||||||
|
from .utils cimport (
|
||||||
|
represent_provider,
|
||||||
|
deepcopy,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Configuration(Provider):
|
||||||
|
"""Configuration provider."""
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
"""Initializer."""
|
||||||
|
self.__name = name
|
||||||
|
self.__value = None
|
||||||
|
self.__children = dict()
|
||||||
|
super(Configuration, self).__init__()
|
||||||
|
|
||||||
|
def __deepcopy__(self, memo):
|
||||||
|
"""Create and return full copy of provider."""
|
||||||
|
copied = memo.get(id(self))
|
||||||
|
if copied is not None:
|
||||||
|
return copied
|
||||||
|
|
||||||
|
copied = self.__class__(self.__name)
|
||||||
|
copied.update(deepcopy(self.__value))
|
||||||
|
|
||||||
|
for overriding_provider in self.overridden:
|
||||||
|
copied.override(deepcopy(overriding_provider, memo))
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return represent_provider(provider=self, provides=self.__name)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""Return child configuration provider."""
|
||||||
|
cdef Configuration child_provider
|
||||||
|
cdef object value
|
||||||
|
|
||||||
|
child_provider = self.__children.get(name)
|
||||||
|
|
||||||
|
if child_provider is None:
|
||||||
|
child_provider = self.__class__(self._get_child_name(name))
|
||||||
|
|
||||||
|
if isinstance(self.__value, dict):
|
||||||
|
child_provider.update(self.__value.get(name))
|
||||||
|
|
||||||
|
self.__children[name] = child_provider
|
||||||
|
|
||||||
|
return child_provider
|
||||||
|
|
||||||
|
cpdef str get_name(self):
|
||||||
|
"""Name of configuration unit."""
|
||||||
|
return self.__name
|
||||||
|
|
||||||
|
cpdef object update(self, value):
|
||||||
|
"""Set configuration options."""
|
||||||
|
cdef Configuration child_provider
|
||||||
|
cdef object child_value
|
||||||
|
|
||||||
|
self.__value = value
|
||||||
|
|
||||||
|
if not isinstance(self.__value, dict):
|
||||||
|
return
|
||||||
|
|
||||||
|
for name in self.__value:
|
||||||
|
child_provider = self.__children.get(name)
|
||||||
|
|
||||||
|
if child_provider is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
child_provider.update(self.__value.get(name))
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs):
|
||||||
|
"""Return result of provided callable's call."""
|
||||||
|
return self.__value
|
||||||
|
|
||||||
|
cpdef str _get_child_name(self, str child_name):
|
||||||
|
cdef str child_full_name
|
||||||
|
|
||||||
|
child_full_name = ''
|
||||||
|
|
||||||
|
if self.__name:
|
||||||
|
child_full_name += self.__name + '.'
|
||||||
|
|
||||||
|
child_full_name += child_name
|
||||||
|
|
||||||
|
return child_full_name
|
96
tests/unit/providers/test_configuration.py
Normal file
96
tests/unit/providers/test_configuration.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
"""Dependency injector config providers unit tests."""
|
||||||
|
|
||||||
|
import unittest2 as unittest
|
||||||
|
|
||||||
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.config = providers.Configuration(name='config')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
del self.config
|
||||||
|
|
||||||
|
def test_providers_are_providers(self):
|
||||||
|
self.assertTrue(providers.is_provider(self.config.a))
|
||||||
|
self.assertTrue(providers.is_provider(self.config.a.b))
|
||||||
|
self.assertTrue(providers.is_provider(self.config.a.b.c))
|
||||||
|
self.assertTrue(providers.is_provider(self.config.a.b.d))
|
||||||
|
|
||||||
|
def test_providers_are_not_delegates(self):
|
||||||
|
self.assertFalse(providers.is_delegated(self.config.a))
|
||||||
|
self.assertFalse(providers.is_delegated(self.config.a.b))
|
||||||
|
self.assertFalse(providers.is_delegated(self.config.a.b.c))
|
||||||
|
self.assertFalse(providers.is_delegated(self.config.a.b.d))
|
||||||
|
|
||||||
|
def test_providers_identity(self):
|
||||||
|
self.assertIs(self.config.a, self.config.a)
|
||||||
|
self.assertIs(self.config.a.b, self.config.a.b)
|
||||||
|
self.assertIs(self.config.a.b.c, self.config.a.b.c)
|
||||||
|
self.assertIs(self.config.a.b.d, self.config.a.b.d)
|
||||||
|
|
||||||
|
def test_get_name(self):
|
||||||
|
self.assertEqual(self.config.a.b.c.get_name(), 'config.a.b.c')
|
||||||
|
|
||||||
|
def test_providers_value_setting(self):
|
||||||
|
a = self.config.a
|
||||||
|
ab = self.config.a.b
|
||||||
|
abc = self.config.a.b.c
|
||||||
|
abd = self.config.a.b.d
|
||||||
|
|
||||||
|
self.config.update({'a': {'b': {'c': 1, 'd': 2}}})
|
||||||
|
|
||||||
|
self.assertEqual(a(), {'b': {'c': 1, 'd': 2}})
|
||||||
|
self.assertEqual(ab(), {'c': 1, 'd': 2})
|
||||||
|
self.assertEqual(abc(), 1)
|
||||||
|
self.assertEqual(abd(), 2)
|
||||||
|
|
||||||
|
def test_value_of_undefined_option(self):
|
||||||
|
self.assertIsNone(self.config.a())
|
||||||
|
|
||||||
|
def test_deepcopy(self):
|
||||||
|
provider = providers.Configuration('config')
|
||||||
|
provider_copy = providers.deepcopy(provider)
|
||||||
|
|
||||||
|
self.assertIsNot(provider, provider_copy)
|
||||||
|
self.assertIsInstance(provider, providers.Configuration)
|
||||||
|
|
||||||
|
def test_deepcopy_from_memo(self):
|
||||||
|
provider = providers.Configuration('config')
|
||||||
|
provider_copy_memo = providers.Configuration('config')
|
||||||
|
|
||||||
|
provider_copy = providers.deepcopy(
|
||||||
|
provider, memo={id(provider): provider_copy_memo})
|
||||||
|
|
||||||
|
self.assertIs(provider_copy, provider_copy_memo)
|
||||||
|
|
||||||
|
def test_deepcopy_overridden(self):
|
||||||
|
provider = providers.Configuration('config')
|
||||||
|
object_provider = providers.Object(object())
|
||||||
|
|
||||||
|
provider.override(object_provider)
|
||||||
|
|
||||||
|
provider_copy = providers.deepcopy(provider)
|
||||||
|
object_provider_copy = provider_copy.overridden[0]
|
||||||
|
|
||||||
|
self.assertIsNot(provider, provider_copy)
|
||||||
|
self.assertIsInstance(provider, providers.Configuration)
|
||||||
|
|
||||||
|
self.assertIsNot(object_provider, object_provider_copy)
|
||||||
|
self.assertIsInstance(object_provider_copy, providers.Object)
|
||||||
|
|
||||||
|
def test_repr(self):
|
||||||
|
self.assertEqual(repr(self.config),
|
||||||
|
'<dependency_injector.providers.configuration.'
|
||||||
|
'Configuration({0}) at {1}>'.format(
|
||||||
|
repr('config'),
|
||||||
|
hex(id(self.config))))
|
||||||
|
|
||||||
|
def test_repr_child(self):
|
||||||
|
self.assertEqual(repr(self.config.a.b.c),
|
||||||
|
'<dependency_injector.providers.configuration.'
|
||||||
|
'Configuration({0}) at {1}>'.format(
|
||||||
|
repr('config.a.b.c'),
|
||||||
|
hex(id(self.config.a.b.c))))
|
Loading…
Reference in New Issue
Block a user