mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-26 03:23:58 +03:00
Merge branch 'release/3.11.0' into master
This commit is contained in:
commit
0e50b1d379
|
@ -351,7 +351,7 @@ Next example demonstrates run of example application defined above:
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Configure platform:
|
# Configure platform:
|
||||||
Core.config.update({'database': {'dsn': ':memory:'},
|
Core.config.override({'database': {'dsn': ':memory:'},
|
||||||
'aws': {'access_key_id': 'KEY',
|
'aws': {'access_key_id': 'KEY',
|
||||||
'secret_access_key': 'SECRET'},
|
'secret_access_key': 'SECRET'},
|
||||||
'auth': {'token_ttl': 3600}})
|
'auth': {'token_ttl': 3600}})
|
||||||
|
|
|
@ -7,6 +7,13 @@ that were made in every particular version.
|
||||||
From version 0.7.6 *Dependency Injector* framework strictly
|
From version 0.7.6 *Dependency Injector* framework strictly
|
||||||
follows `Semantic versioning`_
|
follows `Semantic versioning`_
|
||||||
|
|
||||||
|
3.11.0
|
||||||
|
------
|
||||||
|
- Improve ``Configuration`` provider overriding logic.
|
||||||
|
- Refactor ``Configuration`` provider.
|
||||||
|
- Improve ``DependenciesContainer`` provider overriding logic.
|
||||||
|
- Update "services" example miniapp.
|
||||||
|
- Update "bundles" example miniapp.
|
||||||
|
|
||||||
3.10.0
|
3.10.0
|
||||||
------
|
------
|
||||||
|
|
|
@ -23,8 +23,7 @@ class Core(containers.DeclarativeContainer):
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Initializing containers
|
# Initializing containers
|
||||||
core = Core()
|
core = Core(config={'database': {'dsn': ':memory:'},
|
||||||
core.config.update({'database': {'dsn': ':memory:'},
|
|
||||||
'aws': {'access_key_id': 'KEY',
|
'aws': {'access_key_id': 'KEY',
|
||||||
'secret_access_key': 'SECRET'}})
|
'secret_access_key': 'SECRET'}})
|
||||||
users = Users(database=core.sqlite)
|
users = Users(database=core.sqlite)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from containers import Core, Application
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Configure platform:
|
# Configure platform:
|
||||||
Core.config.update({'database': {'dsn': ':memory:'},
|
Core.config.override({'database': {'dsn': ':memory:'},
|
||||||
'aws': {'access_key_id': 'KEY',
|
'aws': {'access_key_id': 'KEY',
|
||||||
'secret_access_key': 'SECRET'},
|
'secret_access_key': 'SECRET'},
|
||||||
'auth': {'token_ttl': 3600}})
|
'auth': {'token_ttl': 3600}})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Dependency injector top-level package."""
|
"""Dependency injector top-level package."""
|
||||||
|
|
||||||
__version__ = '3.10.0'
|
__version__ = '3.11.0'
|
||||||
"""Version number that follows semantic versioning.
|
"""Version number that follows semantic versioning.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -71,16 +71,10 @@ cdef class CallableDelegate(Delegate):
|
||||||
|
|
||||||
|
|
||||||
# Configuration providers
|
# Configuration providers
|
||||||
cdef class Configuration(Provider):
|
cdef class Configuration(Object):
|
||||||
cdef str __name
|
cdef str __name
|
||||||
cdef object __value
|
|
||||||
cdef dict __children
|
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)
|
|
||||||
|
|
||||||
|
|
||||||
# Factory providers
|
# Factory providers
|
||||||
cdef class Factory(Provider):
|
cdef class Factory(Provider):
|
||||||
|
|
|
@ -427,7 +427,6 @@ cdef class DependenciesContainer(Object):
|
||||||
Dependencies container provider is used to implement late static binding
|
Dependencies container provider is used to implement late static binding
|
||||||
for a set of providers of a particular container.
|
for a set of providers of a particular container.
|
||||||
|
|
||||||
|
|
||||||
Example code:
|
Example code:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -520,6 +519,29 @@ cdef class DependenciesContainer(Object):
|
||||||
self._override_providers(container=provider)
|
self._override_providers(container=provider)
|
||||||
return super(DependenciesContainer, self).override(provider)
|
return super(DependenciesContainer, self).override(provider)
|
||||||
|
|
||||||
|
def reset_last_overriding(self):
|
||||||
|
"""Reset last overriding provider.
|
||||||
|
|
||||||
|
:raise: :py:exc:`dependency_injector.errors.Error` if provider is not
|
||||||
|
overridden.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
for child in self.__providers.values():
|
||||||
|
try:
|
||||||
|
child.reset_last_overriding()
|
||||||
|
except Error:
|
||||||
|
pass
|
||||||
|
super(DependenciesContainer, self).reset_last_overriding()
|
||||||
|
|
||||||
|
def reset_override(self):
|
||||||
|
"""Reset all overriding providers.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
for child in self.__providers.values():
|
||||||
|
child.reset_override()
|
||||||
|
super(DependenciesContainer, self).reset_override()
|
||||||
|
|
||||||
cpdef object _override_providers(self, object container):
|
cpdef object _override_providers(self, object container):
|
||||||
"""Override providers with providers from provided container."""
|
"""Override providers with providers from provided container."""
|
||||||
|
@ -823,7 +845,7 @@ cdef class CallableDelegate(Delegate):
|
||||||
super(Delegate, self).__init__(callable)
|
super(Delegate, self).__init__(callable)
|
||||||
|
|
||||||
|
|
||||||
cdef class Configuration(Provider):
|
cdef class Configuration(Object):
|
||||||
"""Configuration provider.
|
"""Configuration provider.
|
||||||
|
|
||||||
Configuration provider helps with implementing late static binding of
|
Configuration provider helps with implementing late static binding of
|
||||||
|
@ -836,7 +858,7 @@ cdef class Configuration(Provider):
|
||||||
print(config.section1.option1()) # None
|
print(config.section1.option1()) # None
|
||||||
print(config.section1.option2()) # None
|
print(config.section1.option2()) # None
|
||||||
|
|
||||||
config.update({'section1': {'option1': 1,
|
config.override({'section1': {'option1': 1,
|
||||||
'option2': 2}})
|
'option2': 2}})
|
||||||
|
|
||||||
print(config.section1.option1()) # 1
|
print(config.section1.option1()) # 1
|
||||||
|
@ -852,12 +874,10 @@ cdef class Configuration(Provider):
|
||||||
:param default: Default values of configuration unit.
|
:param default: Default values of configuration unit.
|
||||||
:type default: dict
|
:type default: dict
|
||||||
"""
|
"""
|
||||||
|
super(Configuration, self).__init__(default)
|
||||||
|
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self.__value = None
|
self.__children = self._create_children(default)
|
||||||
self.__children = dict()
|
|
||||||
if default is not None:
|
|
||||||
self.update(default)
|
|
||||||
super(Configuration, self).__init__()
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
"""Create and return full copy of provider."""
|
"""Create and return full copy of provider."""
|
||||||
|
@ -868,7 +888,7 @@ cdef class Configuration(Provider):
|
||||||
return copied
|
return copied
|
||||||
|
|
||||||
copied = self.__class__(self.__name)
|
copied = self.__class__(self.__name)
|
||||||
copied.__value = deepcopy(self.__value, memo)
|
copied.__provides = deepcopy(self.__provides, memo)
|
||||||
copied.__children = deepcopy(self.__children, memo)
|
copied.__children = deepcopy(self.__children, memo)
|
||||||
|
|
||||||
self._copy_overridings(copied)
|
self._copy_overridings(copied)
|
||||||
|
@ -884,9 +904,6 @@ cdef class Configuration(Provider):
|
||||||
|
|
||||||
def __getattr__(self, str name):
|
def __getattr__(self, str name):
|
||||||
"""Return child configuration provider."""
|
"""Return child configuration provider."""
|
||||||
cdef Configuration child_provider
|
|
||||||
cdef object value
|
|
||||||
|
|
||||||
if name.startswith('__') and name.endswith('__'):
|
if name.startswith('__') and name.endswith('__'):
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
'\'{cls}\' object has no attribute '
|
'\'{cls}\' object has no attribute '
|
||||||
|
@ -896,55 +913,103 @@ cdef class Configuration(Provider):
|
||||||
child_provider = self.__children.get(name)
|
child_provider = self.__children.get(name)
|
||||||
|
|
||||||
if child_provider is None:
|
if child_provider is None:
|
||||||
child_provider = self.__class__(self._get_child_name(name))
|
child_name = self._get_child_full_name(name)
|
||||||
|
child_provider = self.__class__(child_name)
|
||||||
|
|
||||||
if isinstance(self.__value, dict):
|
value = self.__call__()
|
||||||
child_provider.update(self.__value.get(name))
|
if isinstance(value, dict):
|
||||||
|
child_value = value.get(name)
|
||||||
|
child_provider.override(child_value)
|
||||||
|
|
||||||
self.__children[name] = child_provider
|
self.__children[name] = child_provider
|
||||||
|
|
||||||
return child_provider
|
return child_provider
|
||||||
|
|
||||||
cpdef str get_name(self):
|
def get_name(self):
|
||||||
"""Name of configuration unit."""
|
"""Name of configuration unit."""
|
||||||
return self.__name
|
return self.__name
|
||||||
|
|
||||||
cpdef object update(self, value):
|
def override(self, provider):
|
||||||
|
"""Override provider with another provider.
|
||||||
|
|
||||||
|
:param provider: Overriding provider.
|
||||||
|
:type provider: :py:class:`Provider`
|
||||||
|
|
||||||
|
:raise: :py:exc:`dependency_injector.errors.Error`
|
||||||
|
|
||||||
|
:return: Overriding context.
|
||||||
|
:rtype: :py:class:`OverridingContext`
|
||||||
|
"""
|
||||||
|
overriding_context = super(Configuration, self).override(provider)
|
||||||
|
|
||||||
|
value = self.__call__()
|
||||||
|
if not isinstance(value, dict):
|
||||||
|
return
|
||||||
|
|
||||||
|
for name in value:
|
||||||
|
child_provider = self.__children.get(name)
|
||||||
|
if child_provider is None:
|
||||||
|
continue
|
||||||
|
child_provider.override(value.get(name))
|
||||||
|
|
||||||
|
return overriding_context
|
||||||
|
|
||||||
|
def reset_last_overriding(self):
|
||||||
|
"""Reset last overriding provider.
|
||||||
|
|
||||||
|
:raise: :py:exc:`dependency_injector.errors.Error` if provider is not
|
||||||
|
overridden.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
for child in self.__children.values():
|
||||||
|
try:
|
||||||
|
child.reset_last_overriding()
|
||||||
|
except Error:
|
||||||
|
pass
|
||||||
|
super(Configuration, self).reset_last_overriding()
|
||||||
|
|
||||||
|
def reset_override(self):
|
||||||
|
"""Reset all overriding providers.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
for child in self.__children.values():
|
||||||
|
child.reset_override()
|
||||||
|
super(Configuration, self).reset_override()
|
||||||
|
|
||||||
|
def update(self, value):
|
||||||
"""Set configuration options.
|
"""Set configuration options.
|
||||||
|
|
||||||
|
.. deprecated:: 3.11
|
||||||
|
|
||||||
|
Use :py:meth:`Configuration.override` instead.
|
||||||
|
|
||||||
:param value: Value of configuration option.
|
:param value: Value of configuration option.
|
||||||
:type value: object | dict
|
:type value: object | dict
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
cdef Configuration child_provider
|
self.override(value)
|
||||||
cdef object child_value
|
|
||||||
|
|
||||||
self.__value = value
|
def _create_children(self, value):
|
||||||
|
children = dict()
|
||||||
|
|
||||||
if not isinstance(self.__value, dict):
|
if not isinstance(value, dict):
|
||||||
return
|
return children
|
||||||
|
|
||||||
for name in self.__value:
|
for child_name, child_value in value.items():
|
||||||
child_provider = self.__children.get(name)
|
child_full_name = self._get_child_full_name(child_name)
|
||||||
|
child_provider = self.__class__(child_full_name, child_value)
|
||||||
|
children[child_name] = child_provider
|
||||||
|
|
||||||
if child_provider is None:
|
return children
|
||||||
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
|
|
||||||
|
|
||||||
|
def _get_child_full_name(self, child_name):
|
||||||
child_full_name = ''
|
child_full_name = ''
|
||||||
|
|
||||||
if self.__name:
|
if self.__name:
|
||||||
child_full_name += self.__name + '.'
|
child_full_name += self.__name + '.'
|
||||||
|
|
||||||
child_full_name += child_name
|
child_full_name += child_name
|
||||||
|
|
||||||
return child_full_name
|
return child_full_name
|
||||||
|
|
|
@ -341,6 +341,22 @@ class DependenciesContainerTests(unittest.TestCase):
|
||||||
self.assertTrue(dependency.overridden)
|
self.assertTrue(dependency.overridden)
|
||||||
self.assertIs(dependency.last_overriding, self.container.dependency)
|
self.assertIs(dependency.last_overriding, self.container.dependency)
|
||||||
|
|
||||||
|
def test_reset_last_overriding(self):
|
||||||
|
dependency = self.provider.dependency
|
||||||
|
self.provider.override(self.container)
|
||||||
|
self.provider.reset_last_overriding()
|
||||||
|
|
||||||
|
self.assertIsNone(dependency.last_overriding)
|
||||||
|
self.assertIsNone(dependency.last_overriding)
|
||||||
|
|
||||||
|
def test_reset_override(self):
|
||||||
|
dependency = self.provider.dependency
|
||||||
|
self.provider.override(self.container)
|
||||||
|
self.provider.reset_override()
|
||||||
|
|
||||||
|
self.assertFalse(dependency.overridden)
|
||||||
|
self.assertFalse(dependency.overridden)
|
||||||
|
|
||||||
def test_init_with_container_and_providers(self):
|
def test_init_with_container_and_providers(self):
|
||||||
provider = providers.DependenciesContainer(
|
provider = providers.DependenciesContainer(
|
||||||
self.container, dependency=providers.Dependency())
|
self.container, dependency=providers.Dependency())
|
||||||
|
|
|
@ -60,8 +60,33 @@ class ConfigTests(unittest.TestCase):
|
||||||
self.assertEqual(abc(), 1)
|
self.assertEqual(abc(), 1)
|
||||||
self.assertEqual(abd(), 2)
|
self.assertEqual(abd(), 2)
|
||||||
|
|
||||||
def test_providers_with_default_value(self):
|
def test_providers_value_override(self):
|
||||||
|
a = self.config.a
|
||||||
|
ab = self.config.a.b
|
||||||
|
abc = self.config.a.b.c
|
||||||
|
abd = self.config.a.b.d
|
||||||
|
|
||||||
|
self.config.override({'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_providers_with_already_overridden_value(self):
|
||||||
|
self.config.override({'a': {'b': {'c': 1, 'd': 2}}})
|
||||||
|
|
||||||
|
a = self.config.a
|
||||||
|
ab = self.config.a.b
|
||||||
|
abc = self.config.a.b.c
|
||||||
|
abd = self.config.a.b.d
|
||||||
|
|
||||||
|
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_providers_with_default_value(self):
|
||||||
self.config = providers.Configuration(
|
self.config = providers.Configuration(
|
||||||
name='config', default={'a': {'b': {'c': 1, 'd': 2}}})
|
name='config', default={'a': {'b': {'c': 1, 'd': 2}}})
|
||||||
|
|
||||||
|
@ -75,6 +100,27 @@ class ConfigTests(unittest.TestCase):
|
||||||
self.assertEqual(abc(), 1)
|
self.assertEqual(abc(), 1)
|
||||||
self.assertEqual(abd(), 2)
|
self.assertEqual(abd(), 2)
|
||||||
|
|
||||||
|
def test_providers_with_default_value_overriding(self):
|
||||||
|
self.config = providers.Configuration(
|
||||||
|
name='config', default={'a': {'b': {'c': 1, 'd': 2}}})
|
||||||
|
|
||||||
|
self.assertEqual(self.config.a(), {'b': {'c': 1, 'd': 2}})
|
||||||
|
self.assertEqual(self.config.a.b(), {'c': 1, 'd': 2})
|
||||||
|
self.assertEqual(self.config.a.b.c(), 1)
|
||||||
|
self.assertEqual(self.config.a.b.d(), 2)
|
||||||
|
|
||||||
|
self.config.override({'a': {'b': {'c': 3, 'd': 4}}})
|
||||||
|
self.assertEqual(self.config.a(), {'b': {'c': 3, 'd': 4}})
|
||||||
|
self.assertEqual(self.config.a.b(), {'c': 3, 'd': 4})
|
||||||
|
self.assertEqual(self.config.a.b.c(), 3)
|
||||||
|
self.assertEqual(self.config.a.b.d(), 4)
|
||||||
|
|
||||||
|
self.config.reset_override()
|
||||||
|
self.assertEqual(self.config.a(), {'b': {'c': 1, 'd': 2}})
|
||||||
|
self.assertEqual(self.config.a.b(), {'c': 1, 'd': 2})
|
||||||
|
self.assertEqual(self.config.a.b.c(), 1)
|
||||||
|
self.assertEqual(self.config.a.b.d(), 2)
|
||||||
|
|
||||||
def test_value_of_undefined_option(self):
|
def test_value_of_undefined_option(self):
|
||||||
self.assertIsNone(self.config.a())
|
self.assertIsNone(self.config.a())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user