fix: better permissive support
This commit is contained in:
parent
7761758096
commit
7ae1b48f4a
3 changed files with 179 additions and 123 deletions
|
@ -21,7 +21,7 @@ from functools import wraps
|
|||
from copy import deepcopy
|
||||
|
||||
|
||||
from .error import ConfigError, LeadershipError, ValueErrorWarning
|
||||
from .error import ConfigError, LeadershipError, ValueErrorWarning, PropertiesOptionError
|
||||
from .i18n import _
|
||||
from .setting import ConfigBag, owners, groups, undefined, \
|
||||
FORBIDDEN_SET_PROPERTIES, SPECIAL_PROPERTIES, \
|
||||
|
@ -92,6 +92,7 @@ class CommonTiramisu(TiramisuHelp):
|
|||
_allow_dynoption = False
|
||||
|
||||
def _set_subconfig(self) -> None:
|
||||
if not self._subconfig:
|
||||
self._subconfig = self._config_bag.context.get_sub_config(self._config_bag,
|
||||
self._path,
|
||||
self._index,
|
||||
|
@ -119,6 +120,7 @@ def option_type(typ):
|
|||
)]
|
||||
kwargs['is_group'] = True
|
||||
return func(self, options_bag, *args[1:], **kwargs)
|
||||
self._set_subconfig()
|
||||
option = self._subconfig.option
|
||||
error_type = None
|
||||
if 'dynamic' in types:
|
||||
|
@ -194,6 +196,7 @@ class CommonTiramisuOption(CommonTiramisu):
|
|||
self._path = path
|
||||
self._index = index
|
||||
self._config_bag = config_bag
|
||||
self._subconfig = None
|
||||
self._set_subconfig()
|
||||
|
||||
|
||||
|
@ -292,6 +295,11 @@ class _TiramisuOptionOptionDescription:
|
|||
return 'optiondescription'
|
||||
return option.get_type()
|
||||
|
||||
@option_type(['option', 'symlink', 'with_or_without_index'])
|
||||
def extra(self, extra):
|
||||
"""Get de option extra"""
|
||||
return self._subconfig.option.impl_get_extra(extra)
|
||||
|
||||
@option_type(['option', 'optiondescription', 'symlink', 'with_or_without_index'])
|
||||
def isdynamic(self,
|
||||
*,
|
||||
|
@ -342,17 +350,17 @@ class _TiramisuOptionOptionDescription:
|
|||
return ret
|
||||
|
||||
@option_type(['dynamic', 'with_or_without_index'])
|
||||
def suffixes(self,
|
||||
def identifiers(self,
|
||||
only_self: bool=False,
|
||||
uncalculated: bool=False,
|
||||
):
|
||||
"""Get suffixes for dynamic option"""
|
||||
"""Get identifiers for dynamic option"""
|
||||
if not only_self:
|
||||
return self._subconfig.suffixes
|
||||
return self._subconfig.identifiers
|
||||
if not self._subconfig.option.impl_is_optiondescription() or \
|
||||
not self._subconfig.option.impl_is_dynoptiondescription():
|
||||
raise ConfigError(_(f'the option {self._subconfig.path} is not a dynamic option, cannot get suffixes with only_self parameter to True'))
|
||||
return self._subconfig.option.get_suffixes(self._subconfig.parent,
|
||||
raise ConfigError(_(f'the option {self._subconfig.path} is not a dynamic option, cannot get identifiers with only_self parameter to True'))
|
||||
return self._subconfig.option.get_identifiers(self._subconfig.parent,
|
||||
uncalculated=uncalculated,
|
||||
)
|
||||
|
||||
|
@ -571,6 +579,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
|
|||
class TiramisuOptionInformation(CommonTiramisuOption):
|
||||
"""Manage option's informations"""
|
||||
_validate_properties = False
|
||||
_allow_dynoption = True
|
||||
|
||||
@option_type(['option', 'optiondescription', 'with_or_without_index', 'symlink'])
|
||||
def get(self,
|
||||
|
@ -670,8 +679,8 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
option = self._subconfig.option
|
||||
if not isinstance(value, Calculation) and option.impl_is_leader() and \
|
||||
len(value) < self._subconfig.parent.get_length_leadership():
|
||||
raise LeadershipError(_('cannot reduce length of the leader "{}"'
|
||||
'').format(option.impl_get_display_name(self._subconfig)))
|
||||
raise LeadershipError(_('cannot reduce length of the leader {}'
|
||||
'').format(option.impl_get_display_name(self._subconfig, with_quote=True)))
|
||||
values = self._config_bag.context.get_values()
|
||||
return values.set_value(self._subconfig,
|
||||
value
|
||||
|
@ -753,6 +762,32 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet):
|
|||
"""Length for a leadership"""
|
||||
return self._subconfig.parent.get_length_leadership()
|
||||
|
||||
def mandatory(self):
|
||||
"""Return path of options with mandatory property without any value"""
|
||||
subconfig = self._subconfig
|
||||
if subconfig.option.impl_is_optiondescription():
|
||||
ori_config_bag = self._subconfig.config_bag
|
||||
config_bag = ori_config_bag.copy()
|
||||
config_bag.properties -= {'mandatory', 'empty', 'warnings'}
|
||||
config_bag.set_permissive()
|
||||
self._subconfig.config_bag = config_bag
|
||||
options = []
|
||||
for subconfig in self._config_bag.context.walk(self._subconfig,
|
||||
only_mandatory=True,
|
||||
):
|
||||
options.append(TiramisuOption(subconfig.path,
|
||||
subconfig.index,
|
||||
ori_config_bag,
|
||||
subconfig=subconfig,
|
||||
))
|
||||
self._subconfig.config_bag = ori_config_bag
|
||||
return options
|
||||
try:
|
||||
self._config_bag.context.walk_valid_value(self._subconfig, only_mandatory=True)
|
||||
except PropertiesOptionError as err:
|
||||
return err.proptype == ['mandatory'] or err.proptype == ['empty']
|
||||
return False
|
||||
|
||||
|
||||
def _registers(_registers: Dict[str, type],
|
||||
prefix: str,
|
||||
|
@ -808,9 +843,6 @@ class TiramisuOption(CommonTiramisu,
|
|||
self._index = index
|
||||
self._config_bag = config_bag
|
||||
self._allow_dynoption = allow_dynoption
|
||||
if subconfig is None:
|
||||
self._set_subconfig()
|
||||
else:
|
||||
self._subconfig = subconfig
|
||||
if not self._registers:
|
||||
_registers(self._registers, 'TiramisuOption')
|
||||
|
@ -831,6 +863,7 @@ class TiramisuOption(CommonTiramisu,
|
|||
raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc}) for {self._path}'))
|
||||
#
|
||||
def __iter__(self):
|
||||
self._set_subconfig()
|
||||
for sub_subconfig in self._subconfig.get_children(True):
|
||||
yield TiramisuOption(sub_subconfig.path,
|
||||
sub_subconfig.index,
|
||||
|
@ -841,6 +874,7 @@ class TiramisuOption(CommonTiramisu,
|
|||
@option_type('optiondescription')
|
||||
def group_type(self):
|
||||
"""Get type for an optiondescription (only for optiondescription)"""
|
||||
self._set_subconfig()
|
||||
return self._subconfig.option.impl_get_group_type()
|
||||
|
||||
@option_type('optiondescription')
|
||||
|
@ -850,6 +884,7 @@ class TiramisuOption(CommonTiramisu,
|
|||
uncalculated: bool=False,
|
||||
):
|
||||
"""List options inside an option description (by default list only option)"""
|
||||
self._set_subconfig()
|
||||
return self._list(self._subconfig,
|
||||
validate_properties,
|
||||
uncalculated=uncalculated,
|
||||
|
@ -1335,12 +1370,15 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk):
|
|||
return 'optiondescription'
|
||||
|
||||
def list(self,
|
||||
*,
|
||||
validate_properties: bool=True,
|
||||
uncalculated: bool=False,
|
||||
):
|
||||
"""List options (by default list only option)"""
|
||||
root = self._config_bag.context.get_root(self._config_bag)
|
||||
return self._list(root,
|
||||
validate_properties,
|
||||
uncalculated=uncalculated,
|
||||
)
|
||||
|
||||
def _load_dict(self,
|
||||
|
|
|
@ -115,12 +115,12 @@ class ParamOption(Param):
|
|||
|
||||
|
||||
class ParamDynOption(ParamOption):
|
||||
__slots__ = ('suffixes',
|
||||
__slots__ = ('identifiers',
|
||||
'optional',
|
||||
)
|
||||
def __init__(self,
|
||||
option: 'Option',
|
||||
suffixes: list[str],
|
||||
identifiers: list[str],
|
||||
notraisepropertyerror: bool=False,
|
||||
raisepropertyerror: bool=False,
|
||||
optional: bool=False,
|
||||
|
@ -129,7 +129,11 @@ class ParamDynOption(ParamOption):
|
|||
notraisepropertyerror,
|
||||
raisepropertyerror,
|
||||
)
|
||||
self.suffixes = suffixes
|
||||
if not isinstance(identifiers, list):
|
||||
raise Exception(f'identifiers in ParamDynOption must be a list, not {identifiers}')
|
||||
if not isinstance(optional, bool):
|
||||
raise Exception(f'optional in ParamDynOption must be a boolean, not {optional}')
|
||||
self.identifiers = identifiers
|
||||
self.optional = optional
|
||||
|
||||
|
||||
|
@ -212,12 +216,12 @@ class ParamIndex(Param):
|
|||
__slots__ = tuple()
|
||||
|
||||
|
||||
class ParamSuffix(Param):
|
||||
__slots__ = ('suffix_index',)
|
||||
class ParamIdentifier(Param):
|
||||
__slots__ = ('identifier_index',)
|
||||
def __init__(self,
|
||||
suffix_index: int=-1,
|
||||
identifier_index: int=-1,
|
||||
) -> None:
|
||||
self.suffix_index = suffix_index
|
||||
self.identifier_index = identifier_index
|
||||
|
||||
|
||||
class Calculation:
|
||||
|
@ -345,7 +349,7 @@ def manager_callback(callback: Callable,
|
|||
properties=undefined,
|
||||
):
|
||||
option = subconfig.option
|
||||
if option.impl_is_follower() and apply_index is False:
|
||||
if option.impl_is_follower() and (subconfig.index is None or apply_index is False):
|
||||
value = []
|
||||
for idx in range(subconfig.parent.get_length_leadership()):
|
||||
subconfig = get_option_bag(config_bag,
|
||||
|
@ -374,10 +378,11 @@ def manager_callback(callback: Callable,
|
|||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||
if isinstance(param, ParamSelfOption) or param.notraisepropertyerror or param.raisepropertyerror:
|
||||
raise err from err
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_('unable to carry out a calculation for {}, {}').format(display_name, err)) from err
|
||||
except ValueError as err:
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig)
|
||||
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(display_name, err)) from err
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ValueError(_('the option {0} is used in a calculation but is invalid ({1})').format(display_name, err)) from err
|
||||
except AttributeError as err:
|
||||
if isinstance(param, ParamDynOption) and param.optional:
|
||||
# cannot acces, simulate a propertyerror
|
||||
|
@ -385,8 +390,8 @@ def manager_callback(callback: Callable,
|
|||
['configerror'],
|
||||
config_bag.context.get_settings(),
|
||||
)
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig)
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err
|
||||
return value
|
||||
|
||||
def get_option_bag(config_bag,
|
||||
|
@ -398,16 +403,13 @@ def manager_callback(callback: Callable,
|
|||
properties=undefined,
|
||||
):
|
||||
# don't validate if option is option that we tried to validate
|
||||
config_bag = config_bag.copy()
|
||||
if for_settings:
|
||||
config_bag.properties = config_bag.properties - {'warnings'}
|
||||
config_bag.set_permissive()
|
||||
if not for_settings:
|
||||
config_bag.properties -= {'warnings'}
|
||||
if self_calc:
|
||||
config_bag.unrestraint()
|
||||
config_bag.remove_validation()
|
||||
# root = config_bag.context.get_root(config_bag)
|
||||
try:
|
||||
subsubconfig = config_bag.context.get_sub_config(config_bag,
|
||||
opt.impl_getpath(),
|
||||
|
@ -419,10 +421,11 @@ def manager_callback(callback: Callable,
|
|||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||
if param.notraisepropertyerror or param.raisepropertyerror:
|
||||
raise err from err
|
||||
display_name = option.impl_get_display_name(subconfig)
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
|
||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_('unable to carry out a calculation for {}, {}').format(display_name, err)) from err
|
||||
except ValueError as err:
|
||||
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option.impl_get_display_name(subconfig), err)) from err
|
||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ValueError(_('the option {0} is used in a calculation but is invalid ({1})').format(display_name, err)) from err
|
||||
except AttributeError as err:
|
||||
if isinstance(param, ParamDynOption) and param.optional:
|
||||
# cannot acces, simulate a propertyerror
|
||||
|
@ -430,8 +433,8 @@ def manager_callback(callback: Callable,
|
|||
['configerror'],
|
||||
config_bag.context.get_settings(),
|
||||
)
|
||||
display_name = option.impl_get_display_name(subconfig)
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err
|
||||
return subsubconfig
|
||||
|
||||
if isinstance(param, ParamValue):
|
||||
|
@ -447,7 +450,9 @@ def manager_callback(callback: Callable,
|
|||
true_path=subconfig.path,
|
||||
)
|
||||
if isinstance(isubconfig, list):
|
||||
raise ConfigError(f'cannot find information for "{option.impl_get_display_name(subconfig)}", "{search_option.impl_get_display_name(None)}" is a dynamic option')
|
||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
search_name = search_option.impl_get_display_name(None, with_quote=True)
|
||||
raise ConfigError(f'cannot find information for {display_name}, {search_name} is a dynamic option')
|
||||
else:
|
||||
isubconfig = get_option_bag(config_bag,
|
||||
param.option,
|
||||
|
@ -464,17 +469,17 @@ def manager_callback(callback: Callable,
|
|||
param.default_value,
|
||||
)
|
||||
except ValueError as err:
|
||||
display_name = option.impl_get_display_name(subconfig)
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err
|
||||
|
||||
if isinstance(param, ParamIndex):
|
||||
return index
|
||||
|
||||
if isinstance(param, ParamSuffix):
|
||||
if isinstance(param, ParamIdentifier):
|
||||
if not option.issubdyn() and (not option.impl_is_optiondescription() or not option.impl_is_dynoptiondescription()):
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig)
|
||||
raise ConfigError(_(f'option "{display_name}" is not a dynoptiondescription or in a dynoptiondescription'))
|
||||
return subconfig.suffixes[param.suffix_index]
|
||||
display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise ConfigError(_(f'option {display_name} is not a dynoptiondescription or in a dynoptiondescription'))
|
||||
return subconfig.identifiers[param.identifier_index]
|
||||
|
||||
if isinstance(param, ParamSelfOption):
|
||||
value = calc_self(param,
|
||||
|
@ -490,7 +495,6 @@ def manager_callback(callback: Callable,
|
|||
|
||||
if isinstance(param, ParamOption):
|
||||
callbk_option = param.option
|
||||
config_bag = subconfig.config_bag
|
||||
if index is not None and callbk_option.impl_get_leadership() and \
|
||||
callbk_option.impl_get_leadership().in_same_leadership(option):
|
||||
if not callbk_option.impl_is_follower():
|
||||
|
@ -506,8 +510,7 @@ def manager_callback(callback: Callable,
|
|||
with_index = False
|
||||
if callbk_option.issubdyn():
|
||||
if isinstance(param, ParamDynOption):
|
||||
#callbk_option = callbk_option.to_sub_dyoption(param.suffixes)
|
||||
suffixes = param.suffixes.copy()
|
||||
identifiers = param.identifiers.copy()
|
||||
paths = callbk_option.impl_getpath().split('.')
|
||||
parents = [config_bag.context.get_root(config_bag)]
|
||||
subconfigs_is_a_list = False
|
||||
|
@ -520,9 +523,18 @@ def manager_callback(callback: Callable,
|
|||
allow_dynoption=True,
|
||||
)
|
||||
if doption.impl_is_dynoptiondescription():
|
||||
if suffixes:
|
||||
suffix = suffixes.pop(0)
|
||||
name = doption.impl_getname(suffix)
|
||||
if not identifiers:
|
||||
identifier = None
|
||||
else:
|
||||
identifier = identifiers.pop(0)
|
||||
if not identifier:
|
||||
subconfigs_is_a_list = True
|
||||
new_parents.extend(parent.dyn_to_subconfig(doption,
|
||||
True,
|
||||
)
|
||||
)
|
||||
else:
|
||||
name = doption.impl_getname(identifier)
|
||||
try:
|
||||
doption = parent.option.get_child(name,
|
||||
config_bag,
|
||||
|
@ -534,14 +546,8 @@ def manager_callback(callback: Callable,
|
|||
None,
|
||||
True,
|
||||
name=name,
|
||||
suffix=suffix,
|
||||
identifier=identifier,
|
||||
))
|
||||
else:
|
||||
subconfigs_is_a_list = True
|
||||
new_parents.extend(parent.dyn_to_subconfig(doption,
|
||||
True,
|
||||
)
|
||||
)
|
||||
else:
|
||||
new_parents.append(parent.get_child(doption,
|
||||
None,
|
||||
|
@ -625,11 +631,13 @@ def carry_out_calculation(subconfig: 'SubConfig',
|
|||
Values could have multiple values only when key is ''."""
|
||||
option = subconfig.option
|
||||
if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None:
|
||||
raise ConfigError(f'the follower "{option.impl_get_display_name(subconfig)}" must have index in carry_out_calculation!')
|
||||
raise ConfigError(f'the follower {option.impl_get_display_name(subconfig, with_quote=True)} must have index in carry_out_calculation!')
|
||||
def fake_items(iterator):
|
||||
return ((None, i) for i in iterator)
|
||||
args = []
|
||||
kwargs = {}
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.set_permissive()
|
||||
if callback_params:
|
||||
for key, param in chain(fake_items(callback_params.args), callback_params.kwargs.items()):
|
||||
try:
|
||||
|
@ -667,18 +675,18 @@ def carry_out_calculation(subconfig: 'SubConfig',
|
|||
if args or kwargs:
|
||||
raise LeadershipError(_('the "{}" function with positional arguments "{}" '
|
||||
'and keyword arguments "{}" must not return '
|
||||
'a list ("{}") for the follower option "{}"'
|
||||
'a list ("{}") for the follower option {}'
|
||||
'').format(callback.__name__,
|
||||
args,
|
||||
kwargs,
|
||||
ret,
|
||||
option.impl_get_display_name(subconfig)))
|
||||
option.impl_get_display_name(subconfig, with_quote=True)))
|
||||
else:
|
||||
raise LeadershipError(_('the "{}" function must not return a list ("{}") '
|
||||
'for the follower option "{}"'
|
||||
'for the follower option {}'
|
||||
'').format(callback.__name__,
|
||||
ret,
|
||||
option.impl_get_display_name(subconfig)))
|
||||
option.impl_get_display_name(subconfig, with_quote=True)))
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -702,22 +710,22 @@ def calculate(subconfig,
|
|||
if allow_value_error:
|
||||
if force_value_warning:
|
||||
raise ValueWarning(str(err))
|
||||
raise err
|
||||
raise err from err
|
||||
error = err
|
||||
except ConfigError as err:
|
||||
raise err from err
|
||||
except Exception as err:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
error = err
|
||||
if args or kwargs:
|
||||
msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '
|
||||
'for option "{2}"').format(str(error),
|
||||
'for option {2}').format(str(error),
|
||||
callback.__name__,
|
||||
subconfig.option.impl_get_display_name(subconfig),
|
||||
subconfig.option.impl_get_display_name(subconfig, with_quote=True),
|
||||
args,
|
||||
kwargs)
|
||||
else:
|
||||
msg = _('unexpected error "{0}" in function "{1}" for option "{2}"'
|
||||
msg = _('unexpected error "{0}" in function "{1}" for option {2}'
|
||||
'').format(str(error),
|
||||
callback.__name__,
|
||||
subconfig.option.impl_get_display_name(subconfig))
|
||||
subconfig.option.impl_get_display_name(subconfig, with_quote=True))
|
||||
raise ConfigError(msg) from error
|
||||
|
|
|
@ -182,10 +182,11 @@ class SubConfig:
|
|||
'index',
|
||||
'path',
|
||||
'true_path',
|
||||
'properties',
|
||||
'_properties',
|
||||
'apply_requires',
|
||||
'transitive_properties',
|
||||
'is_dynamic',
|
||||
'suffixes',
|
||||
'identifiers',
|
||||
'_length',
|
||||
)
|
||||
def __init__(self,
|
||||
|
@ -194,14 +195,14 @@ class SubConfig:
|
|||
path: str,
|
||||
config_bag: ConfigBag,
|
||||
parent: Optional['SubConfig'],
|
||||
suffixes: Optional[list[str]],
|
||||
identifiers: Optional[list[str]],
|
||||
*,
|
||||
true_path: Optional[str]=None,
|
||||
properties: Union[list[str], undefined]=undefined,
|
||||
validate_properties: bool=True,
|
||||
) -> None:
|
||||
self.index = index
|
||||
self.suffixes = suffixes
|
||||
self.identifiers = identifiers
|
||||
self.option = option
|
||||
self.config_bag = config_bag
|
||||
self.parent = parent
|
||||
|
@ -210,38 +211,47 @@ class SubConfig:
|
|||
if true_path is None:
|
||||
true_path = path
|
||||
is_follower = not option.impl_is_optiondescription() and option.impl_is_follower()
|
||||
apply_requires = not is_follower or index is not None
|
||||
self.apply_requires = not is_follower or index is not None
|
||||
self.true_path = true_path
|
||||
settings = config_bag.context.get_settings()
|
||||
if parent and parent.is_dynamic or self.option.impl_is_dynoptiondescription():
|
||||
self.is_dynamic = True
|
||||
else:
|
||||
self.is_dynamic = False
|
||||
if properties is undefined:
|
||||
if path is None:
|
||||
self.properties = frozenset()
|
||||
else:
|
||||
self.properties = frozenset()
|
||||
self._properties = properties
|
||||
if validate_properties:
|
||||
self.properties = settings.getproperties(self,
|
||||
if self.path and self._properties is undefined:
|
||||
settings = config_bag.context.get_settings()
|
||||
self._properties = settings.getproperties(self,
|
||||
apply_requires=False,
|
||||
)
|
||||
self.config_bag.context.get_settings().validate_properties(self)
|
||||
self.properties = settings.getproperties(self,
|
||||
apply_requires=apply_requires,
|
||||
)
|
||||
else:
|
||||
self.properties = properties
|
||||
if validate_properties:
|
||||
self._properties = undefined
|
||||
self.config_bag.context.get_settings().validate_properties(self)
|
||||
if apply_requires and self.option.impl_is_optiondescription():
|
||||
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()
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
if self._properties is undefined:
|
||||
if self.path is None:
|
||||
self._properties = frozenset()
|
||||
else:
|
||||
settings = self.config_bag.context.get_settings()
|
||||
self._properties = frozenset()
|
||||
self._properties = settings.getproperties(self,
|
||||
apply_requires=self.apply_requires,
|
||||
)
|
||||
return self._properties
|
||||
|
||||
@properties.setter
|
||||
def properties(self, properties):
|
||||
self._properties = properties
|
||||
|
||||
def __repr__(self):
|
||||
return f'<SubConfig path={self.path}, index={self.index}>'
|
||||
|
@ -253,9 +263,9 @@ class SubConfig:
|
|||
true_path: Optional[str]=None,
|
||||
) -> List['SubConfig']:
|
||||
config_bag = self.config_bag
|
||||
for suffix in child.get_suffixes(self):
|
||||
for identifier in child.get_identifiers(self):
|
||||
try:
|
||||
name = child.impl_getname(suffix)
|
||||
name = child.impl_getname(identifier)
|
||||
if not validate_properties:
|
||||
properties = None
|
||||
else:
|
||||
|
@ -263,7 +273,7 @@ class SubConfig:
|
|||
yield self.get_child(child,
|
||||
None,
|
||||
validate_properties,
|
||||
suffix=suffix,
|
||||
identifier=identifier,
|
||||
name=name,
|
||||
properties=properties,
|
||||
true_path=true_path,
|
||||
|
@ -323,7 +333,7 @@ class SubConfig:
|
|||
*,
|
||||
properties=undefined,
|
||||
allow_dynoption: bool=False,
|
||||
suffix: Optional[str]=None,
|
||||
identifier: Optional[str]=None,
|
||||
name: Optional[str]=None,
|
||||
check_index: bool=True,
|
||||
config_bag: ConfigBag=None,
|
||||
|
@ -338,19 +348,19 @@ class SubConfig:
|
|||
path = self.get_path(name,
|
||||
option,
|
||||
)
|
||||
if suffix is None:
|
||||
suffixes = self.suffixes
|
||||
if identifier is None:
|
||||
identifiers = self.identifiers
|
||||
else:
|
||||
if self.suffixes:
|
||||
suffixes = self.suffixes + [suffix]
|
||||
if self.identifiers:
|
||||
identifiers = self.identifiers + [identifier]
|
||||
else:
|
||||
suffixes = [suffix]
|
||||
identifiers = [identifier]
|
||||
subsubconfig = SubConfig(option,
|
||||
index,
|
||||
path,
|
||||
self.config_bag,
|
||||
self,
|
||||
suffixes,
|
||||
identifiers,
|
||||
properties=properties,
|
||||
validate_properties=validate_properties,
|
||||
true_path=true_path,
|
||||
|
@ -363,7 +373,7 @@ class SubConfig:
|
|||
if index >= length:
|
||||
raise LeadershipError(_(f'index "{index}" is greater than the leadership '
|
||||
f'length "{length}" for option '
|
||||
f'"{option.impl_get_display_name(subsubconfig)}"'))
|
||||
f'{option.impl_get_display_name(subsubconfig, with_quote=True)}'))
|
||||
return subsubconfig
|
||||
|
||||
def get_path(self,
|
||||
|
@ -393,7 +403,7 @@ class SubConfig:
|
|||
path,
|
||||
cconfig_bag,
|
||||
self,
|
||||
self.suffixes,
|
||||
self.identifiers,
|
||||
validate_properties=False,
|
||||
)
|
||||
self._length = len(cconfig_bag.context.get_value(subconfig))
|
||||
|
@ -587,7 +597,7 @@ class _Config(CCache):
|
|||
raise AttributeError(_("no option found in config"
|
||||
" with these criteria"))
|
||||
|
||||
def _walk_valid_value(self,
|
||||
def walk_valid_value(self,
|
||||
subconfig,
|
||||
only_mandatory,
|
||||
):
|
||||
|
@ -649,19 +659,19 @@ class _Config(CCache):
|
|||
option = subconfig.option.get_child(name,
|
||||
config_bag,
|
||||
subconfig,
|
||||
with_suffix=True,
|
||||
with_identifier=True,
|
||||
allow_dynoption=allow_dynoption,
|
||||
)
|
||||
if isinstance(option, tuple):
|
||||
suffix, option = option
|
||||
identifier, option = option
|
||||
else:
|
||||
suffix = None
|
||||
identifier = None
|
||||
subconfig = subconfig.get_child(option,
|
||||
index_,
|
||||
validate_properties,
|
||||
properties=properties,
|
||||
name=name,
|
||||
suffix=suffix,
|
||||
identifier=identifier,
|
||||
true_path=true_path_,
|
||||
)
|
||||
return subconfig
|
||||
|
@ -710,7 +720,7 @@ class _Config(CCache):
|
|||
only_mandatory: bool,
|
||||
):
|
||||
try:
|
||||
value = self._walk_valid_value(subconfig,
|
||||
value = self.walk_valid_value(subconfig,
|
||||
only_mandatory,
|
||||
)
|
||||
except PropertiesOptionError as err:
|
||||
|
@ -764,8 +774,8 @@ class _Config(CCache):
|
|||
length = subconfig.parent.get_length_leadership()
|
||||
follower_len = self.get_values().get_max_length(subconfig.path)
|
||||
if follower_len > length:
|
||||
option_name = subconfig.option.impl_get_display_name(subconfig)
|
||||
raise LeadershipError(_(f'the follower option "{option_name}" '
|
||||
option_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True)
|
||||
raise LeadershipError(_(f'the follower option {option_name} '
|
||||
f'has greater length ({follower_len}) than the leader '
|
||||
f'length ({length})'))
|
||||
self.get_settings().validate_mandatory(subconfig,
|
||||
|
|
Loading…
Reference in a new issue