feat: better identifiers retrieve
This commit is contained in:
parent
f3a7344b58
commit
6d56e25524
7 changed files with 157 additions and 62 deletions
6
.cz.toml
6
.cz.toml
|
|
@ -1,6 +0,0 @@
|
|||
[tool.commitizen]
|
||||
name = "cz_conventional_commits"
|
||||
tag_format = "$version"
|
||||
version_scheme = "semver"
|
||||
version = "4.1.0"
|
||||
update_changelog_on_bump = true
|
||||
|
|
@ -508,8 +508,8 @@ def test_dyndescription_subdyn():
|
|||
assert set(cfg.option('od.dod2val1.dodval1.st').property.get()) == {'validator'}
|
||||
assert set(cfg.option('od.dod2val1.dodval1.st').property.get(uncalculated=True)) == {'validator'}
|
||||
assert set(cfg.option('od.dod2.dod.st').property.get(uncalculated=True)) == {'validator'}
|
||||
with pytest.raises(AttributeOptionError):
|
||||
cfg.option('od.dod2.dodval1.st').property.get(uncalculated=True)
|
||||
# with pytest.raises(AttributeOptionError):
|
||||
assert set(cfg.option('od.dod2.dodval1.st').property.get(uncalculated=True)) == {'validator'}
|
||||
assert cfg.option('od.dod2val1.dod.st').property.get(uncalculated=True) == {'validator'}
|
||||
#
|
||||
with pytest.raises(AttributeOptionError):
|
||||
|
|
@ -540,11 +540,13 @@ def test_dyndescription_subdyn():
|
|||
assert cfg.option('od.dod2.dod').group_type() == "default"
|
||||
assert cfg.option('od.dod2val1.dodval1').group_type() == "default"
|
||||
#
|
||||
with pytest.raises(AttributeOptionError):
|
||||
cfg.option('od.dod2.dod').identifiers()
|
||||
assert cfg.option('od.dod2.dod').identifiers() == [['val1', 'val1'], ['val1', 'val2'], ['val2', 'val1'], ['val2', 'val2']]
|
||||
assert cfg.option('od.dod2.dod').identifiers(only_self=True) == ['val1', 'val2']
|
||||
assert cfg.option('od.dod2val1.dodval1').identifiers() == ['val1', 'val1']
|
||||
assert cfg.option('od.dod2val1.dodval1').identifiers(only_self=True) == ['val1', 'val2']
|
||||
assert cfg.option('od.dod2val1.dodval2').identifiers() == ['val1', 'val2']
|
||||
assert cfg.option('od.dod2val1.dod').identifiers() == [['val1', 'val1'], ['val1', 'val2']]
|
||||
assert cfg.option('od.dod2.dodval1.st').identifiers() == [['val1', 'val1'], ['val2', 'val1']]
|
||||
|
||||
|
||||
def test_callback_dyndescription_subdyn():
|
||||
|
|
@ -562,6 +564,37 @@ def test_callback_dyndescription_subdyn():
|
|||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval3.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'lst': ['val1', 'val3']}
|
||||
cfg.option('lst').value.set(["val1", "val3", None])
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval3.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'lst': ['val1', 'val3', None]}
|
||||
assert cfg.option('od.dod2.dod.st').identifiers() == [['val1', 'val1'], ['val1', 'val3'], ['val3', 'val1'], ['val3', 'val3']]
|
||||
assert cfg.option('od.dod2.dod').identifiers(only_self=True) == ['val1', 'val3']
|
||||
assert cfg.option('od.dod2val1.dod.st').identifiers() == [['val1', 'val1'], ['val1', 'val3']]
|
||||
assert cfg.option('od.dod2val1.dodval1.st').identifiers() == ['val1', 'val1']
|
||||
assert cfg.option('od.dod2val1.dodval1').identifiers(only_self=True) == ['val1', 'val3']
|
||||
|
||||
|
||||
def test_callback_dyndescription_subdyn2():
|
||||
lst1 = StrOption('lst1', '', ['val1', 'val2'], multi=True)
|
||||
lst2 = StrOption('lst2', '', ['val3', 'val4'], multi=True)
|
||||
st = StrOption('st', '', 'val1')
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst1))))
|
||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamDynOption(st, [None, 'val1']))), multi=True, properties=('notunique',))
|
||||
dod2 = DynOptionDescription('dod2', '', [dod, out], identifiers=Calculation(return_list, Params(ParamOption(lst2))))
|
||||
od = OptionDescription('od', '', [dod2])
|
||||
od2 = OptionDescription('od', '', [od, lst1, lst2])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_write()
|
||||
#
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval2.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'od.dod2val4.dodval1.st': 'val1', 'od.dod2val4.dodval2.st': 'val1', 'od.dod2val4.out': ['val1', 'val1'], 'lst1': ['val1', 'val2'], 'lst2': ['val3', 'val4']}
|
||||
#
|
||||
cfg.option('lst1').value.set(["val1", "val3"])
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'od.dod2val4.dodval1.st': 'val1', 'od.dod2val4.dodval3.st': 'val1', 'od.dod2val4.out': ['val1', 'val1'], 'lst1': ['val1', 'val3'], 'lst2': ['val3', 'val4']}
|
||||
#
|
||||
cfg.option('lst1').value.set(["val1", "val3", None])
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'od.dod2val4.dodval1.st': 'val1', 'od.dod2val4.dodval3.st': 'val1', 'od.dod2val4.out': ['val1', 'val1'], 'lst1': ['val1', 'val3', None], 'lst2': ['val3', 'val4']}
|
||||
assert cfg.option('od.dod2.dod.st').identifiers() == [['val3', 'val1'], ['val3', 'val3'], ['val4', 'val1'], ['val4', 'val3']]
|
||||
assert cfg.option('od.dod2.dod').identifiers(only_self=True) == ['val1', 'val3']
|
||||
assert cfg.option('od.dod2val3.dod.st').identifiers() == [['val3', 'val1'], ['val3', 'val3']]
|
||||
assert cfg.option('od.dod2val3.dodval1.st').identifiers() == ['val3', 'val1']
|
||||
assert cfg.option('od.dod2val3.dodval1').identifiers(only_self=True) == ['val1', 'val3']
|
||||
|
||||
|
||||
def test_callback_list_dyndescription():
|
||||
|
|
@ -2220,6 +2253,8 @@ def test_leadership_dyndescription_convert():
|
|||
assert cfg.option('od.stval2.st1.st1').owner.isdefault()
|
||||
assert cfg.option('od.stval2.st1.st1').identifiers() == ["val.2"]
|
||||
assert cfg.option('od.stval2.st1.st1').identifiers(convert=True) == ["val2"]
|
||||
assert cfg.option('od.st.st1.st1').identifiers() == [["val.1"], ["val.2"]]
|
||||
assert cfg.option('od.st.st1.st1').identifiers(convert=True) == [["val1"], ["val2"]]
|
||||
assert cfg.option('od.stval2').identifiers(only_self=True) == ["val.1", "val.2"]
|
||||
assert cfg.option('od.stval2').identifiers(only_self=True, convert=True) == ["val1", "val2"]
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1186,7 +1186,6 @@ def test_leadership_requires_leadership(config_type):
|
|||
#
|
||||
cfg.option('activate').value.set(False)
|
||||
if config_type != 'tiramisu-api':
|
||||
# FIXME
|
||||
with pytest.raises(PropertiesOptionError):
|
||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
||||
with pytest.raises(PropertiesOptionError):
|
||||
|
|
|
|||
114
tiramisu/api.py
114
tiramisu/api.py
|
|
@ -135,11 +135,13 @@ class CommonTiramisu(TiramisuHelp):
|
|||
config_bag=self._config_bag,
|
||||
parent=subconfig.parent,
|
||||
identifiers=subconfig.identifiers,
|
||||
identifier=None,
|
||||
true_path=subconfig.true_path,
|
||||
properties=subconfig.properties,
|
||||
validate_properties=False,
|
||||
check_dynamic_without_identifiers=False,
|
||||
)
|
||||
self._subconfig.is_self_dynamic_without_identifiers = subconfig.is_self_dynamic_without_identifiers
|
||||
else:
|
||||
self._subconfig._length = None
|
||||
if not self._subconfig:
|
||||
|
|
@ -148,18 +150,14 @@ class CommonTiramisu(TiramisuHelp):
|
|||
self._config_bag,
|
||||
self._path,
|
||||
self._index,
|
||||
validate_properties=False,
|
||||
validate_properties=self._validate_properties,
|
||||
allow_dynoption=True,
|
||||
)
|
||||
except AssertionError as err:
|
||||
raise ConfigError(str(err))
|
||||
|
||||
|
||||
def option_type(typ):
|
||||
if not isinstance(typ, list):
|
||||
types = [typ]
|
||||
else:
|
||||
types = typ
|
||||
def option_type(types):
|
||||
|
||||
def wrapper(func):
|
||||
@wraps(func)
|
||||
|
|
@ -179,7 +177,7 @@ def option_type(typ):
|
|||
return func(self, options_bag, *args[1:], **kwargs)
|
||||
self._set_subconfig()
|
||||
if (
|
||||
not isinstance(typ, list) or "allow_dynoption" not in typ
|
||||
"allow_dynoption" not in types and not ("dynoption_or_uncalculated" in types and kwargs.get("uncalculated", False) is True)
|
||||
) and self._subconfig.is_dynamic_without_identifiers:
|
||||
raise AttributeOptionError(self._subconfig.path, "option-dynamic")
|
||||
|
||||
|
|
@ -595,43 +593,88 @@ class _TiramisuOptionOptionDescription:
|
|||
)
|
||||
return ret
|
||||
|
||||
def has_identifiers(self):
|
||||
return self._subconfig.is_dynamic_without_identifiers
|
||||
|
||||
@option_type(["dynamic", "with_or_without_index", "allow_dynoption"])
|
||||
def identifiers(
|
||||
self,
|
||||
*,
|
||||
only_self: bool = False,
|
||||
uncalculated: bool = False,
|
||||
convert: bool = False,
|
||||
):
|
||||
"""Get identifiers for dynamic option"""
|
||||
subconfig = self._subconfig
|
||||
if not only_self:
|
||||
if self._subconfig.is_dynamic_without_identifiers and not uncalculated:
|
||||
raise AttributeOptionError(self._subconfig.path, "option-dynamic")
|
||||
if not convert:
|
||||
return self._subconfig.identifiers
|
||||
identifiers = []
|
||||
dynconfig = None
|
||||
while not dynconfig:
|
||||
if subconfig.option.impl_is_optiondescription() and subconfig.option.impl_is_dynoptiondescription():
|
||||
dynconfig = subconfig
|
||||
subconfig = subconfig.parent
|
||||
for identifier in self._subconfig.identifiers:
|
||||
if identifier is None:
|
||||
continue
|
||||
identifiers.append(dynconfig.option.convert_identifier_to_path(identifier))
|
||||
return identifiers
|
||||
if only_self:
|
||||
func = self._identifiers_only_self
|
||||
elif not subconfig.is_dynamic_without_identifiers:
|
||||
func = self._identifiers_all
|
||||
else:
|
||||
func = self._identifiers_all_no_identifiers
|
||||
return func(subconfig, uncalculated, convert)
|
||||
|
||||
def _identifiers_all(self, subconfig, uncalculated, convert):
|
||||
dynconfig = None
|
||||
_subconfig = subconfig
|
||||
while not dynconfig:
|
||||
if _subconfig.option.impl_is_optiondescription() and _subconfig.option.impl_is_dynoptiondescription():
|
||||
dynconfig = _subconfig
|
||||
else:
|
||||
_subconfig = _subconfig.parent
|
||||
identifiers = []
|
||||
for identifier in _subconfig.identifiers:
|
||||
if convert:
|
||||
identifier = dynconfig.option.convert_identifier_to_path(identifier)
|
||||
identifiers.append(identifier)
|
||||
return identifiers
|
||||
|
||||
def _identifiers_all_no_identifiers(self, subconfig, uncalculated, convert):
|
||||
"""dyn{{ identifier }}.var{{ identifier }}.var
|
||||
=> dyn["val1", "val2"]
|
||||
=> var["val3", "val4"]
|
||||
returns [["val1", "val3"], ["val1", "val4"], ["val2", "val3"], ["val2", "val4"]]
|
||||
"""
|
||||
identifiers = []
|
||||
while True:
|
||||
if subconfig.option.impl_is_optiondescription() and subconfig.option.impl_is_dynoptiondescription():
|
||||
if not subconfig.is_self_dynamic_without_identifiers:
|
||||
new_identifiers = [subconfig.identifiers[-1]]
|
||||
else:
|
||||
new_identifiers = subconfig.option.get_identifiers(subconfig.parent, uncalculated=uncalculated, convert=convert)
|
||||
if isinstance(new_identifiers, Calculation):
|
||||
if identifiers:
|
||||
identifiers = [[new_identifiers] + old_identifiers for old_identifiers in identifiers]
|
||||
else:
|
||||
identifiers = [new_identifiers]
|
||||
elif identifiers:
|
||||
identifiers = [[identifier] + old_identifiers for identifier in new_identifiers for old_identifiers in identifiers]
|
||||
else:
|
||||
identifiers = [[identifier] for identifier in new_identifiers]
|
||||
subconfig = subconfig.parent
|
||||
if subconfig is None:
|
||||
break
|
||||
return identifiers
|
||||
|
||||
def _identifiers_only_self(self, subconfig, uncalculated, convert):
|
||||
if (
|
||||
not self._subconfig.option.impl_is_optiondescription()
|
||||
or not self._subconfig.option.impl_is_dynoptiondescription()
|
||||
not subconfig.option.impl_is_optiondescription()
|
||||
or not subconfig.option.impl_is_dynoptiondescription()
|
||||
):
|
||||
raise ConfigError(
|
||||
_(
|
||||
"the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True"
|
||||
).format(self._subconfig.path),
|
||||
).format(subconfig.path),
|
||||
subconfig=subconfig,
|
||||
)
|
||||
return self._subconfig.option.get_identifiers(
|
||||
self._subconfig.parent,
|
||||
dynconfig = None
|
||||
_subconfig = subconfig
|
||||
while not dynconfig:
|
||||
if _subconfig.option.impl_is_optiondescription() and _subconfig.option.impl_is_dynoptiondescription():
|
||||
dynconfig = _subconfig
|
||||
_subconfig = _subconfig.parent
|
||||
return dynconfig.option.get_identifiers(
|
||||
dynconfig.parent,
|
||||
uncalculated=uncalculated,
|
||||
convert=convert,
|
||||
)
|
||||
|
|
@ -1010,7 +1053,7 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
|
||||
_validate_properties = True
|
||||
|
||||
@option_type(["option", "symlink", "with_index", "optiondescription"])
|
||||
@option_type(["option", "symlink", "with_index", "optiondescription", "dynoption_or_uncalculated"])
|
||||
def get(
|
||||
self,
|
||||
*,
|
||||
|
|
@ -1074,7 +1117,7 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
values.reset(self._subconfig)
|
||||
|
||||
@option_type(
|
||||
["option", "with_or_without_index", "symlink", "dont_validate_property"]
|
||||
["option", "with_or_without_index", "symlink", "dont_validate_property", "dynoption_or_uncalculated"]
|
||||
)
|
||||
def default(
|
||||
self,
|
||||
|
|
@ -1113,7 +1156,7 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
return False
|
||||
return True
|
||||
|
||||
@option_type(["choice", "with_index", "allow_dynoption"])
|
||||
@option_type(["choice", "with_index_or_uncalculated", "allow_dynoption"])
|
||||
def list(
|
||||
self,
|
||||
*,
|
||||
|
|
@ -1127,7 +1170,7 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
uncalculated,
|
||||
)
|
||||
|
||||
@option_type("leader")
|
||||
@option_type(["leader"])
|
||||
def pop(
|
||||
self,
|
||||
index: int,
|
||||
|
|
@ -1350,7 +1393,7 @@ class TiramisuOption(
|
|||
remotable=remotable,
|
||||
)
|
||||
|
||||
@option_type("optiondescription")
|
||||
@option_type(["optiondescription"])
|
||||
def dict(
|
||||
self,
|
||||
clearable: str = "all",
|
||||
|
|
@ -1363,7 +1406,7 @@ class TiramisuOption(
|
|||
self._load_dict(clearable, remotable)
|
||||
return self._tiramisu_dict.todict(form)
|
||||
|
||||
@option_type("optiondescription")
|
||||
@option_type(["optiondescription"])
|
||||
def updates(
|
||||
self,
|
||||
body: List,
|
||||
|
|
@ -1445,17 +1488,20 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet):
|
|||
only_mandatory=True,
|
||||
):
|
||||
if id(subconfig.config_bag) != id(config_bag):
|
||||
old_is_dynamic_without_identifiers = subconfig.is_self_dynamic_without_identifiers
|
||||
subconfig = subconfig.__class__(option=subconfig.option,
|
||||
index=subconfig.index,
|
||||
path=subconfig.path,
|
||||
config_bag=config_bag,
|
||||
parent=subconfig.parent,
|
||||
identifiers=subconfig.identifiers,
|
||||
identifier=None,
|
||||
true_path=subconfig.true_path,
|
||||
properties=subconfig.properties,
|
||||
validate_properties=False,
|
||||
check_dynamic_without_identifiers=False,
|
||||
)
|
||||
subconfig.is_self_dynamic_without_identifiers = old_is_dynamic_without_identifiers
|
||||
else:
|
||||
subconfig._length = None
|
||||
options.append(
|
||||
|
|
|
|||
|
|
@ -691,6 +691,7 @@ def manager_callback(
|
|||
subconfigs_is_a_list = False
|
||||
for name in paths:
|
||||
new_parents = []
|
||||
identifier = undefined
|
||||
for parent in parents:
|
||||
doption = parent.option.get_child(
|
||||
name,
|
||||
|
|
@ -699,11 +700,12 @@ def manager_callback(
|
|||
allow_dynoption=True,
|
||||
)
|
||||
if doption.impl_is_dynoptiondescription():
|
||||
if not identifiers:
|
||||
identifier = None
|
||||
else:
|
||||
identifier = identifiers.pop(0)
|
||||
if not identifier:
|
||||
if identifier is undefined:
|
||||
if not identifiers:
|
||||
identifier = None
|
||||
else:
|
||||
identifier = identifiers.pop(0)
|
||||
if identifier is None:
|
||||
subconfigs_is_a_list = True
|
||||
new_parents.extend(
|
||||
parent.dyn_to_subconfig(
|
||||
|
|
@ -879,17 +881,20 @@ def carry_out_calculation(
|
|||
kwargs = {}
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.set_permissive()
|
||||
old_is_dynamic_without_identifiers = subconfig.is_dynamic_without_identifiers
|
||||
subconfig = subconfig.__class__(option=subconfig.option,
|
||||
index=subconfig.index,
|
||||
path=subconfig.path,
|
||||
config_bag=config_bag,
|
||||
parent=subconfig.parent,
|
||||
identifiers=subconfig.identifiers,
|
||||
identifier=None,
|
||||
true_path=subconfig.true_path,
|
||||
properties=subconfig.properties,
|
||||
validate_properties=False,
|
||||
check_dynamic_without_identifiers=False,
|
||||
)
|
||||
subconfig.is_dynamic_without_identifiers = old_is_dynamic_without_identifiers
|
||||
if callback_params:
|
||||
for key, param in chain(
|
||||
fake_items(callback_params.args), callback_params.kwargs.items()
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ class SubConfig:
|
|||
"transitive_properties",
|
||||
"is_dynamic",
|
||||
"is_dynamic_without_identifiers",
|
||||
"is_self_dynamic_without_identifiers",
|
||||
"identifiers",
|
||||
"_length",
|
||||
)
|
||||
|
|
@ -287,6 +288,7 @@ class SubConfig:
|
|||
config_bag: ConfigBag,
|
||||
parent: Optional["SubConfig"],
|
||||
identifiers: Optional[list[str]],
|
||||
identifier: Optional[str],
|
||||
*,
|
||||
true_path: Optional[str] = None,
|
||||
# for python 3.9 properties: Union[list[str], undefined] = undefined,
|
||||
|
|
@ -308,6 +310,7 @@ class SubConfig:
|
|||
)
|
||||
self.apply_requires = not is_follower or index is not None
|
||||
self.true_path = true_path
|
||||
self.is_self_dynamic_without_identifiers = identifier is None
|
||||
if self.option.impl_is_dynoptiondescription():
|
||||
self.is_dynamic = True
|
||||
self.is_dynamic_without_identifiers = identifiers is None or (
|
||||
|
|
@ -321,7 +324,8 @@ class SubConfig:
|
|||
and self.is_dynamic_without_identifiers
|
||||
!= parent.is_dynamic_without_identifiers
|
||||
):
|
||||
raise AttributeOptionError(true_path, "option-dynamic")
|
||||
self.is_dynamic_without_identifiers = True
|
||||
# raise AttributeOptionError(true_path, "option-dynamic")
|
||||
elif parent:
|
||||
self.is_dynamic = parent.is_dynamic
|
||||
self.is_dynamic_without_identifiers = parent.is_dynamic_without_identifiers
|
||||
|
|
@ -339,15 +343,14 @@ class SubConfig:
|
|||
self.config_bag.context.get_settings().validate_properties(self)
|
||||
self._properties = undefined
|
||||
self.config_bag.context.get_settings().validate_properties(self)
|
||||
if self.apply_requires and self.option.impl_is_optiondescription():
|
||||
if self.path and self.properties is not None:
|
||||
settings = config_bag.context.get_settings()
|
||||
self.transitive_properties = settings.calc_transitive_properties(
|
||||
self,
|
||||
self.properties,
|
||||
)
|
||||
else:
|
||||
self.transitive_properties = frozenset()
|
||||
if validate_properties and self.apply_requires and self.option.impl_is_optiondescription() and self.path and self.properties is not None:
|
||||
settings = config_bag.context.get_settings()
|
||||
self.transitive_properties = settings.calc_transitive_properties(
|
||||
self,
|
||||
self.properties,
|
||||
)
|
||||
else:
|
||||
self.transitive_properties = frozenset()
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
|
|
@ -515,6 +518,7 @@ class SubConfig:
|
|||
config_bag,
|
||||
self,
|
||||
identifiers,
|
||||
identifier,
|
||||
properties=properties,
|
||||
validate_properties=validate_properties,
|
||||
true_path=true_path,
|
||||
|
|
@ -560,8 +564,10 @@ class SubConfig:
|
|||
cconfig_bag,
|
||||
self,
|
||||
self.identifiers,
|
||||
None,
|
||||
validate_properties=False,
|
||||
)
|
||||
subconfig.is_self_dynamic_without_identifiers = self.is_self_dynamic_without_identifiers
|
||||
#FIXME
|
||||
#self._length = len(cconfig_bag.context.get_value(subconfig))
|
||||
length = len(cconfig_bag.context.get_value(subconfig))
|
||||
|
|
@ -664,16 +670,19 @@ class SubConfig:
|
|||
def change_context(self, context) -> "SubConfig":
|
||||
config_bag = self.config_bag.copy()
|
||||
config_bag.context = context
|
||||
return SubConfig(
|
||||
subconfig = SubConfig(
|
||||
self.option,
|
||||
self.index,
|
||||
self.path,
|
||||
config_bag,
|
||||
self.parent,
|
||||
self.identifiers,
|
||||
None,
|
||||
true_path=self.true_path,
|
||||
validate_properties=False,
|
||||
)
|
||||
subconfig.is_self_dynamic_without_identifiers = self.is_self_dynamic_without_identifiers
|
||||
return subconfig
|
||||
|
||||
|
||||
class _Config(CCache):
|
||||
|
|
@ -761,6 +770,7 @@ class _Config(CCache):
|
|||
config_bag,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
def get_sub_config(
|
||||
|
|
|
|||
|
|
@ -227,7 +227,13 @@ class Option(BaseOption):
|
|||
default = getattr(self, "_default", undefined)
|
||||
if default is undefined:
|
||||
if is_multi:
|
||||
default = []
|
||||
if self.impl_is_follower():
|
||||
if submulti:
|
||||
default = getattr(self, "_default_multi", [])
|
||||
else:
|
||||
default = getattr(self, "_default_multi", None)
|
||||
else:
|
||||
default = []
|
||||
else:
|
||||
default = None
|
||||
elif is_multi and isinstance(default, tuple):
|
||||
|
|
|
|||
Loading…
Reference in a new issue