Skip to content

Commit 840ac00

Browse files
committed
Fix required configuration option cache invalidation
1 parent f193f39 commit 840ac00

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

src/dependency_injector/providers.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ cdef class ConfigurationOption(Provider):
117117
cdef Configuration _root
118118
cdef dict _children
119119
cdef bint _required
120+
cdef object _required_option
120121
cdef object _cache
121122

122123

src/dependency_injector/providers.pyx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,7 @@ cdef class ConfigurationOption(Provider):
15221522
self._root = root
15231523
self._children = {}
15241524
self._required = required
1525+
self._required_option = None
15251526
self._cache = UNDEFINED
15261527
super().__init__()
15271528

@@ -1537,6 +1538,7 @@ cdef class ConfigurationOption(Provider):
15371538
copied._root = deepcopy(self._root, memo)
15381539
copied._children = deepcopy(self._children, memo)
15391540
copied._required = self._required
1541+
copied._required_option = deepcopy(self._required_option, memo)
15401542
self._copy_overridings(copied, memo)
15411543
return copied
15421544

@@ -1604,7 +1606,11 @@ cdef class ConfigurationOption(Provider):
16041606
return TypedConfigurationOption(callback, self, *args, **kwargs)
16051607

16061608
def required(self):
1607-
return self.__class__(self._name, self._root, required=True)
1609+
if self._required:
1610+
return self
1611+
if self._required_option is None:
1612+
self._required_option = self.__class__(self._name, self._root, required=True)
1613+
return self._required_option
16081614

16091615
def is_required(self):
16101616
return self._required
@@ -1626,6 +1632,9 @@ cdef class ConfigurationOption(Provider):
16261632
for provider in self._children.values():
16271633
provider.reset_cache()
16281634

1635+
if self._required_option is not None:
1636+
self._required_option.reset_cache()
1637+
16291638
for provider in self.overrides:
16301639
if isinstance(provider, (Configuration, ConfigurationOption)):
16311640
provider.reset_cache()

tests/unit/providers/configuration/test_config_py2_py3.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ def test_required(config):
121121
provider()
122122

123123

124+
def test_required_cache_is_reset_after_option_override():
125+
class Container(containers.DeclarativeContainer):
126+
config = providers.Configuration()
127+
singleton = providers.Singleton(dict, value=config.a.required())
128+
129+
container = Container()
130+
container.config.a.from_value("initial")
131+
132+
assert container.singleton() == {"value": "initial"}
133+
134+
with container.config.a.override("overridden"):
135+
container.singleton.reset()
136+
assert container.singleton() == {"value": "overridden"}
137+
138+
container.singleton.reset()
139+
assert container.singleton() == {"value": "initial"}
140+
141+
124142
def test_required_defined_none(config):
125143
provider = providers.Callable(
126144
lambda value: value,

0 commit comments

Comments
 (0)