fix: black

This commit is contained in:
egarette@silique.fr 2025-05-12 08:45:39 +02:00
parent bb1f117ed1
commit 5a4bb343b0
31 changed files with 628 additions and 159 deletions

View file

@ -50,7 +50,9 @@ def tiramisu_display_name(
comment = doc if doc and doc != kls.impl_getname() else "" comment = doc if doc and doc != kls.impl_getname() else ""
if "{{ identifier }}" in comment and subconfig.identifiers: if "{{ identifier }}" in comment and subconfig.identifiers:
comment = comment.replace("{{ identifier }}", str(subconfig.identifiers[-1])) comment = comment.replace("{{ identifier }}", str(subconfig.identifiers[-1]))
path_in_description = values.get_information(context_subconfig, 'path_in_description', True) path_in_description = values.get_information(
context_subconfig, "path_in_description", True
)
if path_in_description or not comment: if path_in_description or not comment:
comment = f" ({comment})" if comment else "" comment = f" ({comment})" if comment else ""
if path_in_description is False: if path_in_description is False:

View file

@ -140,9 +140,7 @@ class Annotator(Walk):
family.path family.path
) )
self.objectspace.informations.add(family.path, "dynamic_variable", path) self.objectspace.informations.add(family.path, "dynamic_variable", path)
self.objectspace.informations.add( self.objectspace.informations.add(family.path, "ymlfiles", family.xmlfiles)
family.path, "ymlfiles", family.xmlfiles
)
def change_modes(self): def change_modes(self):
"""change the mode of variables""" """change the mode of variables"""

View file

@ -115,7 +115,9 @@ class Annotator(Walk): # pylint: disable=R0903
if isinstance(variable.choices, Calculation): if isinstance(variable.choices, Calculation):
continue continue
if variable.choices is None: if variable.choices is None:
msg = _('the variable "{0}" is a "choice" variable but don\'t have any choice').format(variable.path) msg = _(
'the variable "{0}" is a "choice" variable but don\'t have any choice'
).format(variable.path)
raise DictConsistencyError(msg, 19, variable.xmlfiles) raise DictConsistencyError(msg, 19, variable.xmlfiles)
if not variable.mandatory and not variable.multi: if not variable.mandatory and not variable.multi:
self.add_choice_nil(variable) self.add_choice_nil(variable)
@ -132,5 +134,7 @@ class Annotator(Walk): # pylint: disable=R0903
if variable.type != "regexp": if variable.type != "regexp":
continue continue
if variable.regexp is None: if variable.regexp is None:
msg = _('the variable "{0}" is a "regexp" variable but don\'t have any regexp').format(variable.path) msg = _(
'the variable "{0}" is a "regexp" variable but don\'t have any regexp'
).format(variable.path)
raise DictConsistencyError(msg, 66, variable.xmlfiles) raise DictConsistencyError(msg, 66, variable.xmlfiles)

View file

@ -83,13 +83,21 @@ class Annotator(Walk): # pylint: disable=R0903
continue continue
path = variable.path path = variable.path
if variable.type not in ["unix_user", "secret"]: if variable.type not in ["unix_user", "secret"]:
msg = _('only "unix_user" or "secret" variable type can have "secret_manager" attribute, but "{0}" has type "{1}"') msg = _(
raise DictConsistencyError(msg.format(path, variable.type), 56, variable.xmlfiles) 'only "unix_user" or "secret" variable type can have "secret_manager" attribute, but "{0}" has type "{1}"'
)
raise DictConsistencyError(
msg.format(path, variable.type), 56, variable.xmlfiles
)
if variable.multi and path not in self.objectspace.leaders: if variable.multi and path not in self.objectspace.leaders:
msg = _('the variable "{0}" has attribute "secret_manager" but is a multi variable') msg = _(
'the variable "{0}" has attribute "secret_manager" but is a multi variable'
)
raise DictConsistencyError(msg.format(path), 57, variable.xmlfiles) raise DictConsistencyError(msg.format(path), 57, variable.xmlfiles)
if variable.default is not None: if variable.default is not None:
msg = _('the variable "{0}" has attribute "secret_manager" so must not have default value') msg = _(
'the variable "{0}" has attribute "secret_manager" so must not have default value'
)
raise DictConsistencyError(msg.format(path), 59, variable.xmlfiles) raise DictConsistencyError(msg.format(path), 59, variable.xmlfiles)
def convert_variable(self): def convert_variable(self):
@ -106,9 +114,11 @@ class Annotator(Walk): # pylint: disable=R0903
self.objectspace.informations.add( self.objectspace.informations.add(
variable.path, "ymlfiles", variable.xmlfiles variable.path, "ymlfiles", variable.xmlfiles
) )
if variable.version != '1.0' and isinstance(variable.default, VariableCalculation): if variable.version != "1.0" and isinstance(
calculated_variable_path, calculated_variable, identifier = variable.default.get_variable( variable.default, VariableCalculation
self.objectspace ):
calculated_variable_path, calculated_variable, identifier = (
variable.default.get_variable(self.objectspace)
) )
else: else:
calculated_variable = None calculated_variable = None
@ -144,15 +154,27 @@ class Annotator(Walk): # pylint: disable=R0903
return return
if variable.path in self.objectspace.leaders: if variable.path in self.objectspace.leaders:
variable.multi = self.objectspace.multis[variable.path] = True variable.multi = self.objectspace.multis[variable.path] = True
elif variable.version != "1.0" and isinstance(variable.default, VariableCalculation): elif variable.version != "1.0" and isinstance(
calculated_variable_path, calculated_variable, identifier = variable.default.get_variable( variable.default, VariableCalculation
self.objectspace ):
calculated_variable_path, calculated_variable, identifier = (
variable.default.get_variable(self.objectspace)
) )
if calculated_variable is not None: if calculated_variable is not None:
if calculated_variable.multi is None: if calculated_variable.multi is None:
self._convert_variable_multi(calculated_variable) self._convert_variable_multi(calculated_variable)
variable.multi = calc_multi_for_type_variable(variable, calculated_variable_path, calculated_variable, self.objectspace)[1] variable.multi = calc_multi_for_type_variable(
if calculated_variable.path in self.objectspace.followers and variable.mandatory is calculated_variable.mandatory is False and calculated_variable.path.rsplit(".", 1)[0] != variable.path.rsplit(".", 1)[0]: variable,
calculated_variable_path,
calculated_variable,
self.objectspace,
)[1]
if (
calculated_variable.path in self.objectspace.followers
and variable.mandatory is calculated_variable.mandatory is False
and calculated_variable.path.rsplit(".", 1)[0]
!= variable.path.rsplit(".", 1)[0]
):
variable.empty = False variable.empty = False
else: else:
variable.multi = isinstance(variable.default, list) variable.multi = isinstance(variable.default, list)
@ -163,15 +185,18 @@ class Annotator(Walk): # pylint: disable=R0903
calculated_variable, calculated_variable,
) -> None: ) -> None:
# if a variable has a variable as default value, that means the type/params or multi should has same value # if a variable has a variable as default value, that means the type/params or multi should has same value
if not isinstance(variable.default, VariableCalculation) or variable.type is not None: if (
not isinstance(variable.default, VariableCalculation)
or variable.type is not None
):
return return
# copy type and params # copy type and params
variable.type = calculated_variable.type variable.type = calculated_variable.type
if variable.params is None and calculated_variable.params is not None: if variable.params is None and calculated_variable.params is not None:
variable.params = calculated_variable.params variable.params = calculated_variable.params
if variable.type == 'choice' and variable.choices is None: if variable.type == "choice" and variable.choices is None:
variable.choices = calculated_variable.choices variable.choices = calculated_variable.choices
if variable.type == 'regexp' and variable.regexp is None: if variable.type == "regexp" and variable.regexp is None:
variable.regexp = calculated_variable.regexp variable.regexp = calculated_variable.regexp
def _convert_variable( def _convert_variable(

View file

@ -381,8 +381,8 @@ secret_manager:
rougail_process += """ rougail_process += """
alternative_name: {NAME[0]} alternative_name: {NAME[0]}
""".format( """.format(
NAME=normalize_family(process), NAME=normalize_family(process),
) )
rougail_process += """ rougail_process += """
choices: choices:
""" """
@ -409,8 +409,9 @@ secret_manager:
rougail_process += """ {% if _.output is not propertyerror and _.output == 'NAME' %} rougail_process += """ {% if _.output is not propertyerror and _.output == 'NAME' %}
Cannot load structural for NAME output Cannot load structural for NAME output
{% endif %} {% endif %}
""".replace("NAME", hidden_output """.replace(
) "NAME", hidden_output
)
elif process == "user data": elif process == "user data":
rougail_process += """ multi: true rougail_process += """ multi: true
mandatory: false""" mandatory: false"""
@ -475,7 +476,7 @@ default_params:
mandatory: false mandatory: false
default: {value} default: {value}
""" """
# print(rougail_process) # print(rougail_process)
rougail_options += rougail_process rougail_options += rougail_process
convert = FakeRougailConvert(add_extra_options) convert = FakeRougailConvert(add_extra_options)
convert.init() convert.init()

View file

@ -188,7 +188,7 @@ class ParserVariable:
self.output = None self.output = None
self.tiramisu_cache = rougailconfig["tiramisu_cache"] self.tiramisu_cache = rougailconfig["tiramisu_cache"]
self.load_unexist_redefine = rougailconfig["load_unexist_redefine"] self.load_unexist_redefine = rougailconfig["load_unexist_redefine"]
self.secret_pattern = rougailconfig['secret_manager.pattern'] self.secret_pattern = rougailconfig["secret_manager.pattern"]
# change default initkwargs in CONVERT_OPTION # change default initkwargs in CONVERT_OPTION
if hasattr(rougailconfig, "config"): if hasattr(rougailconfig, "config"):
for sub_od in rougailconfig.config.option("default_params"): for sub_od in rougailconfig.config.option("default_params"):
@ -505,7 +505,7 @@ class ParserVariable:
for key, value in obj.items(): for key, value in obj.items():
if not isinstance(key, str): if not isinstance(key, str):
raise DictConsistencyError( raise DictConsistencyError(
f'a key is not in string format: {key}', f"a key is not in string format: {key}",
103, 103,
[filename], [filename],
) )
@ -648,7 +648,8 @@ class ParserVariable:
raise DictConsistencyError( raise DictConsistencyError(
f'"{path}" is not a valid variable, there are additional ' f'"{path}" is not a valid variable, there are additional '
f'attributes: "{", ".join(extra_attrs)}"', f'attributes: "{", ".join(extra_attrs)}"',
65, [filename] 65,
[filename],
) )
self.parse_parameters( self.parse_parameters(
path, path,
@ -687,9 +688,7 @@ class ParserVariable:
msg = f'cannot redefine the inexisting variable "{path}"' msg = f'cannot redefine the inexisting variable "{path}"'
raise DictConsistencyError(msg, 46, [filename]) raise DictConsistencyError(msg, 46, [filename])
obj["path"] = path obj["path"] = path
self.add_variable( self.add_variable(name, obj, filename, family_is_dynamic, parent_dynamic)
name, obj, filename, family_is_dynamic, parent_dynamic
)
if family_is_leadership: if family_is_leadership:
if first_variable: if first_variable:
self.leaders.append(path) self.leaders.append(path)
@ -803,10 +802,11 @@ class ParserVariable:
64, 64,
[filename], [filename],
) )
secret_manager = {"type": "jinja", secret_manager = {
"jinja": self.secret_pattern, "type": "jinja",
"params": obj["secret_manager"], "jinja": self.secret_pattern,
} "params": obj["secret_manager"],
}
self.set_calculation( self.set_calculation(
obj, obj,
"secret_manager", "secret_manager",

View file

@ -151,7 +151,9 @@ class Param(BaseModel):
) -> None: ) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
def to_param(self, attribute_name, objectspace, path, version, namespace, xmlfiles) -> dict: def to_param(
self, attribute_name, objectspace, path, version, namespace, xmlfiles
) -> dict:
return self.model_dump() return self.model_dump()
@ -167,8 +169,12 @@ class VariableParam(Param):
whole: bool = False whole: bool = False
optional: bool = False optional: bool = False
def to_param(self, attribute_name, objectspace, path, version, namespace, xmlfiles) -> dict: def to_param(
param = super().to_param(attribute_name, objectspace, path, version, namespace, xmlfiles) self, attribute_name, objectspace, path, version, namespace, xmlfiles
) -> dict:
param = super().to_param(
attribute_name, objectspace, path, version, namespace, xmlfiles
)
variable, identifier = objectspace.paths.get_with_dynamic( variable, identifier = objectspace.paths.get_with_dynamic(
param["variable"], param["variable"],
path, path,
@ -178,14 +184,20 @@ class VariableParam(Param):
) )
if not variable: if not variable:
if not param.get("optional"): if not param.get("optional"):
msg = _('cannot find variable "{0}" defined in attribute "{1}" for "{2}"').format(param["variable"], attribute_name, path) msg = _(
'cannot find variable "{0}" defined in attribute "{1}" for "{2}"'
).format(param["variable"], attribute_name, path)
raise DictConsistencyError(msg, 22, xmlfiles) raise DictConsistencyError(msg, 22, xmlfiles)
return None return None
if isinstance(variable, objectspace.family): if isinstance(variable, objectspace.family):
msg = _('the variable "{0}" is in fact a family in attribute "{1}" for "{2}"').format(variable["name"], attribute_name, path) msg = _(
'the variable "{0}" is in fact a family in attribute "{1}" for "{2}"'
).format(variable["name"], attribute_name, path)
raise DictConsistencyError(msg, 42, xmlfiles) raise DictConsistencyError(msg, 42, xmlfiles)
if not isinstance(variable, objectspace.variable): if not isinstance(variable, objectspace.variable):
msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format(variable, attribute_name, path) msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format(
variable, attribute_name, path
)
raise DictConsistencyError(msg, 44, xmlfiles) raise DictConsistencyError(msg, 44, xmlfiles)
param["variable"] = variable param["variable"] = variable
if identifier: if identifier:
@ -202,7 +214,9 @@ class IdentifierParam(Param):
**kwargs, **kwargs,
) -> None: ) -> None:
if not kwargs["family_is_dynamic"]: if not kwargs["family_is_dynamic"]:
msg = _('identifier parameter for "{0}" in "{1}" cannot be set none dynamic family').format(kwargs["attribute"], kwargs["path"]) msg = _(
'identifier parameter for "{0}" in "{1}" cannot be set none dynamic family'
).format(kwargs["attribute"], kwargs["path"])
raise DictConsistencyError(msg, 10, kwargs["xmlfiles"]) raise DictConsistencyError(msg, 10, kwargs["xmlfiles"])
super().__init__(**kwargs) super().__init__(**kwargs)
@ -212,8 +226,12 @@ class InformationParam(Param):
information: str information: str
variable: Optional[str] = None variable: Optional[str] = None
def to_param(self, attribute_name, objectspace, path, version, namespace, xmlfiles) -> dict: def to_param(
param = super().to_param(attribute_name, objectspace, path, version, namespace, xmlfiles) self, attribute_name, objectspace, path, version, namespace, xmlfiles
) -> dict:
param = super().to_param(
attribute_name, objectspace, path, version, namespace, xmlfiles
)
if not param["variable"]: if not param["variable"]:
del param["variable"] del param["variable"]
return param return param
@ -225,10 +243,14 @@ class InformationParam(Param):
xmlfiles, xmlfiles,
) )
if not variable: if not variable:
msg = _('cannot find variable "{0}" defined in "{1}" for "{2}"').format(param["variable"], attribute_name, path) msg = _('cannot find variable "{0}" defined in "{1}" for "{2}"').format(
param["variable"], attribute_name, path
)
raise DictConsistencyError(msg, 14, xmlfiles) raise DictConsistencyError(msg, 14, xmlfiles)
if identifier: if identifier:
msg = _('variable "{0}" defined in "{1}" for "{2}" is a dynamic variable').format(param["variable"], attribute_name, path) msg = _(
'variable "{0}" defined in "{1}" for "{2}" is a dynamic variable'
).format(param["variable"], attribute_name, path)
raise DictConsistencyError(msg, 15, xmlfiles) raise DictConsistencyError(msg, 15, xmlfiles)
param["variable"] = variable param["variable"] = variable
return param return param
@ -237,25 +259,37 @@ class InformationParam(Param):
class IndexParam(Param): class IndexParam(Param):
type: str type: str
def to_param(self, attribute_name, objectspace, path, version, namespace, xmlfiles) -> dict: def to_param(
if path not in objectspace.followers and (attribute_name != 'validators' or path not in objectspace.multis): self, attribute_name, objectspace, path, version, namespace, xmlfiles
msg = _('the variable "{0}" is not a follower, so cannot have index type for param in "{1}"').format(path, attribute) ) -> dict:
if path not in objectspace.followers and (
attribute_name != "validators" or path not in objectspace.multis
):
msg = _(
'the variable "{0}" is not a follower, so cannot have index type for param in "{1}"'
).format(path, attribute)
raise DictConsistencyError(msg, 25, xmlfiles) raise DictConsistencyError(msg, 25, xmlfiles)
return super().to_param(attribute_name, objectspace, path, version, namespace, xmlfiles) return super().to_param(
attribute_name, objectspace, path, version, namespace, xmlfiles
)
class NamespaceParam(Param): class NamespaceParam(Param):
type: str type: str
namespace: str namespace: str
def to_param(self, attribute_name, objectspace, path, version, namespace, xmlfiles) -> dict: def to_param(
self, attribute_name, objectspace, path, version, namespace, xmlfiles
) -> dict:
namespace = self.namespace namespace = self.namespace
if namespace: if namespace:
namespace = objectspace.paths[namespace].description namespace = objectspace.paths[namespace].description
return {'type': 'any', return {
'value': namespace, "type": "any",
'key': self.key, "value": namespace,
} "key": self.key,
}
PARAM_TYPES = { PARAM_TYPES = {
"any": AnyParam, "any": AnyParam,
@ -287,7 +321,14 @@ class Calculation(BaseModel):
path = self.ori_path path = self.ori_path
params = {} params = {}
for param_obj in self.params: for param_obj in self.params:
param = param_obj.to_param(self.attribute_name, objectspace, path, self.version, self.namespace, self.xmlfiles) param = param_obj.to_param(
self.attribute_name,
objectspace,
path,
self.version,
self.namespace,
self.xmlfiles,
)
if param is None: if param is None:
continue continue
params[param.pop("key")] = param params[param.pop("key")] = param
@ -454,13 +495,17 @@ class _VariableCalculation(Calculation):
path = self.path path = self.path
else: else:
path = self.ori_path path = self.ori_path
if self.version != "1.0" and objectspace.paths.regexp_relative.search(self.variable): if self.version != "1.0" and objectspace.paths.regexp_relative.search(
self.variable
):
variable_full_path = objectspace.paths.get_full_path( variable_full_path = objectspace.paths.get_full_path(
self.variable, self.variable,
path, path,
) )
elif self.version == "1.0" and "{{ suffix }}" in self.variable: elif self.version == "1.0" and "{{ suffix }}" in self.variable:
variable_full_path = self.variable.replace("{{ suffix }}", "{{ identifier }}") variable_full_path = self.variable.replace(
"{{ suffix }}", "{{ identifier }}"
)
else: else:
variable_full_path = self.variable variable_full_path = self.variable
variable, identifier = objectspace.paths.get_with_dynamic( variable, identifier = objectspace.paths.get_with_dynamic(
@ -472,10 +517,14 @@ class _VariableCalculation(Calculation):
) )
if variable and not isinstance(variable, objectspace.variable): if variable and not isinstance(variable, objectspace.variable):
if isinstance(variable, objectspace.family): if isinstance(variable, objectspace.family):
msg = _('a variable "{0}" is needs in attribute "{1}" for "{2}" but it\'s a family').format(variable_full_path, self.attribute_name, self.path) msg = _(
'a variable "{0}" is needs in attribute "{1}" for "{2}" but it\'s a family'
).format(variable_full_path, self.attribute_name, self.path)
raise DictConsistencyError(msg, 47, self.xmlfiles) raise DictConsistencyError(msg, 47, self.xmlfiles)
else: else:
msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format(variable, self.attribute_name, self.path) msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format(
variable, self.attribute_name, self.path
)
raise DictConsistencyError(msg, 48, self.xmlfiles) raise DictConsistencyError(msg, 48, self.xmlfiles)
return variable_full_path, variable, identifier return variable_full_path, variable, identifier
@ -492,7 +541,9 @@ class _VariableCalculation(Calculation):
path = self.path path = self.path
else: else:
path = self.ori_path path = self.ori_path
msg = _('variable "{0}" has an attribute "{1}" calculated with the unknown variable "{2}"').format(path, self.attribute_name, self.variable) msg = _(
'variable "{0}" has an attribute "{1}" calculated with the unknown variable "{2}"'
).format(path, self.attribute_name, self.variable)
raise DictConsistencyError(msg, 88, self.xmlfiles) raise DictConsistencyError(msg, 88, self.xmlfiles)
return {None: [["example"]]} return {None: [["example"]]}
param = { param = {
@ -509,7 +560,9 @@ class _VariableCalculation(Calculation):
params["__default_value"] = self.default_values params["__default_value"] = self.default_values
if self.allow_none: if self.allow_none:
params["allow_none"] = True params["allow_none"] = True
self.check_multi(objectspace, variable_in_calculation_path, variable_in_calculation) self.check_multi(
objectspace, variable_in_calculation_path, variable_in_calculation
)
if self.path in objectspace.followers: if self.path in objectspace.followers:
multi = objectspace.multis[self.path] == "submulti" multi = objectspace.multis[self.path] == "submulti"
else: else:
@ -518,51 +571,123 @@ class _VariableCalculation(Calculation):
params["__internal_multi"] = True params["__internal_multi"] = True
return params return params
def check_multi(self, objectspace, variable_in_calculation_path, variable_in_calculation): def check_multi(
self, objectspace, variable_in_calculation_path, variable_in_calculation
):
if self.ori_path is None: if self.ori_path is None:
path = self.path path = self.path
else: else:
path = self.ori_path path = self.ori_path
local_variable = objectspace.paths[path] local_variable = objectspace.paths[path]
local_variable_multi, variable_in_calculation_multi = calc_multi_for_type_variable(local_variable, variable_in_calculation_path, variable_in_calculation, objectspace) local_variable_multi, variable_in_calculation_multi = (
calc_multi_for_type_variable(
local_variable,
variable_in_calculation_path,
variable_in_calculation,
objectspace,
)
)
if self.attribute_name == "default": if self.attribute_name == "default":
if variable_in_calculation_multi == 'submulti': if variable_in_calculation_multi == "submulti":
if objectspace.paths.is_dynamic(variable_in_calculation.path): if objectspace.paths.is_dynamic(variable_in_calculation.path):
msg = _('the variable "{0}" has an invalid "{1}" the variable "{2}" is in a sub dynamic option').format(local_variable.path, self.attribute_name, variable_in_calculation.path) msg = _(
'the variable "{0}" has an invalid "{1}" the variable "{2}" is in a sub dynamic option'
).format(
local_variable.path,
self.attribute_name,
variable_in_calculation.path,
)
raise DictConsistencyError(msg, 69, self.xmlfiles) raise DictConsistencyError(msg, 69, self.xmlfiles)
else: else:
msg = _('the leader "{0}" has an invalid "{1}" the follower "{2}" is a multi').format(local_variable.path, self.attribute_name, variable_in_calculation.path) msg = _(
'the leader "{0}" has an invalid "{1}" the follower "{2}" is a multi'
).format(
local_variable.path,
self.attribute_name,
variable_in_calculation.path,
)
raise DictConsistencyError(msg, 74, self.xmlfiles) raise DictConsistencyError(msg, 74, self.xmlfiles)
if not self.inside_list: if not self.inside_list:
if local_variable_multi != variable_in_calculation_multi: if local_variable_multi != variable_in_calculation_multi:
if local_variable_multi: if local_variable_multi:
self.check_variable_in_calculation_multi(local_variable.path, variable_in_calculation_path, variable_in_calculation_multi) self.check_variable_in_calculation_multi(
self.check_variable_in_calculation_not_multi(local_variable.path, variable_in_calculation_path, variable_in_calculation_multi) local_variable.path,
variable_in_calculation_path,
variable_in_calculation_multi,
)
self.check_variable_in_calculation_not_multi(
local_variable.path,
variable_in_calculation_path,
variable_in_calculation_multi,
)
else: else:
self.check_variable_in_calculation_in_list_not_multi(local_variable.path, variable_in_calculation_path, variable_in_calculation_multi) self.check_variable_in_calculation_in_list_not_multi(
local_variable.path,
variable_in_calculation_path,
variable_in_calculation_multi,
)
elif self.attribute_name in ["choices", "dynamic"]: elif self.attribute_name in ["choices", "dynamic"]:
# calculated variable must be a multi # calculated variable must be a multi
if not self.inside_list: if not self.inside_list:
self.check_variable_in_calculation_multi(local_variable.path, variable_in_calculation_path, variable_in_calculation_multi) self.check_variable_in_calculation_multi(
local_variable.path,
variable_in_calculation_path,
variable_in_calculation_multi,
)
else: else:
self.check_variable_in_calculation_in_list_not_multi(local_variable.path, variable_in_calculation_path, variable_in_calculation_multi) self.check_variable_in_calculation_in_list_not_multi(
local_variable.path,
variable_in_calculation_path,
variable_in_calculation_multi,
)
elif variable_in_calculation_multi is True: elif variable_in_calculation_multi is True:
msg = _('the variable "{0}" has an invalid attribute "{1}", the variable "{2}" must not be multi').format(local_variable.path, self.attribute_name, variable_in_calculation_path) msg = _(
'the variable "{0}" has an invalid attribute "{1}", the variable "{2}" must not be multi'
).format(
local_variable.path, self.attribute_name, variable_in_calculation_path
)
raise DictConsistencyError(msg, 23, self.xmlfiles) raise DictConsistencyError(msg, 23, self.xmlfiles)
def check_variable_in_calculation_multi(self, local_variable_path, variable_in_calculation_path, variable_in_calculation_multi): def check_variable_in_calculation_multi(
self,
local_variable_path,
variable_in_calculation_path,
variable_in_calculation_multi,
):
if variable_in_calculation_multi is False: if variable_in_calculation_multi is False:
msg = _('the variable "{0}" has an invalid attribute "{1}", the variable must not be a multi or the variable "{2}" must be multi').format(local_variable_path, self.attribute_name, variable_in_calculation_path) msg = _(
'the variable "{0}" has an invalid attribute "{1}", the variable must not be a multi or the variable "{2}" must be multi'
).format(
local_variable_path, self.attribute_name, variable_in_calculation_path
)
raise DictConsistencyError(msg, 20, self.xmlfiles) raise DictConsistencyError(msg, 20, self.xmlfiles)
def check_variable_in_calculation_not_multi(self, local_variable_path, variable_in_calculation_path, variable_in_calculation_multi): def check_variable_in_calculation_not_multi(
self,
local_variable_path,
variable_in_calculation_path,
variable_in_calculation_multi,
):
if variable_in_calculation_multi is True: if variable_in_calculation_multi is True:
msg = _('the variable "{0}" has an invalid attribute "{1}", the variable must be a multi or the variable "{2}" must not be multi').format(local_variable_path, self.attribute_name, variable_in_calculation_path) msg = _(
'the variable "{0}" has an invalid attribute "{1}", the variable must be a multi or the variable "{2}" must not be multi'
).format(
local_variable_path, self.attribute_name, variable_in_calculation_path
)
raise DictConsistencyError(msg, 21, self.xmlfiles) raise DictConsistencyError(msg, 21, self.xmlfiles)
def check_variable_in_calculation_in_list_not_multi(self, local_variable_path, variable_in_calculation_path, variable_in_calculation_multi): def check_variable_in_calculation_in_list_not_multi(
self,
local_variable_path,
variable_in_calculation_path,
variable_in_calculation_multi,
):
if variable_in_calculation_multi is True: if variable_in_calculation_multi is True:
msg = _('the variable "{0}" has an invalid attribute "{1}", the variable "{2}" is multi but is inside a list').format(local_variable_path, self.attribute_name, variable_in_calculation_path) msg = _(
'the variable "{0}" has an invalid attribute "{1}", the variable "{2}" is multi but is inside a list'
).format(
local_variable_path, self.attribute_name, variable_in_calculation_path
)
raise DictConsistencyError(msg, 18, self.xmlfiles) raise DictConsistencyError(msg, 18, self.xmlfiles)
@ -576,9 +701,15 @@ class VariableCalculation(_VariableCalculation):
objectspace, objectspace,
) -> dict: ) -> dict:
if self.attribute_name != "default" and self.optional: if self.attribute_name != "default" and self.optional:
msg = _('"{0}" attribut shall not have an "optional" attribute for variable "{1}"').format(self.attribute_name, self.variable) msg = _(
'"{0}" attribut shall not have an "optional" attribute for variable "{1}"'
).format(self.attribute_name, self.variable)
raise DictConsistencyError(msg, 33, self.xmlfiles) raise DictConsistencyError(msg, 33, self.xmlfiles)
variable_in_calculation_path, variable_in_calculation, variable_in_calculation_identifier = self.get_variable(objectspace) (
variable_in_calculation_path,
variable_in_calculation,
variable_in_calculation_identifier,
) = self.get_variable(objectspace)
if ( if (
not variable_in_calculation not variable_in_calculation
and self.optional and self.optional
@ -587,8 +718,12 @@ class VariableCalculation(_VariableCalculation):
raise VariableCalculationDependencyError() raise VariableCalculationDependencyError()
if variable_in_calculation and self.attribute_name == "default": if variable_in_calculation and self.attribute_name == "default":
local_variable = objectspace.paths[self.path] local_variable = objectspace.paths[self.path]
if CONVERT_OPTION.get(local_variable.type, {}).get("func", str) != CONVERT_OPTION.get(variable_in_calculation.type, {}).get("func", str): if CONVERT_OPTION.get(local_variable.type, {}).get(
msg = _('variable "{0}" has a default value calculated with "{1}" which has incompatible type').format(self.path, self.variable) "func", str
) != CONVERT_OPTION.get(variable_in_calculation.type, {}).get("func", str):
msg = _(
'variable "{0}" has a default value calculated with "{1}" which has incompatible type'
).format(self.path, self.variable)
raise DictConsistencyError(msg, 67, self.xmlfiles) raise DictConsistencyError(msg, 67, self.xmlfiles)
params = self.get_params( params = self.get_params(
objectspace, objectspace,
@ -613,29 +748,41 @@ class VariablePropertyCalculation(_VariableCalculation):
self, self,
objectspace, objectspace,
) -> dict: ) -> dict:
variable_in_calculation_path, variable_in_calculation, variable_in_calculation_identifier = self.get_variable(objectspace) (
variable_in_calculation_path,
variable_in_calculation,
variable_in_calculation_identifier,
) = self.get_variable(objectspace)
params = self.get_params( params = self.get_params(
objectspace, objectspace,
variable_in_calculation_path, variable_in_calculation_path,
variable_in_calculation, variable_in_calculation,
variable_in_calculation_identifier, variable_in_calculation_identifier,
) )
if objectspace.force_optional and (not params[None] or "variable" not in params[None][0]): if objectspace.force_optional and (
not params[None] or "variable" not in params[None][0]
):
params = {None: [None, None, False]} params = {None: [None, None, False]}
else: else:
variable = params[None][0]["variable"] variable = params[None][0]["variable"]
if self.when is not undefined: if self.when is not undefined:
if self.version == "1.0": if self.version == "1.0":
msg = _('"when" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"').format(self.attribute_name, self.path) msg = _(
'"when" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"'
).format(self.attribute_name, self.path)
raise DictConsistencyError(msg, 103, variable.xmlfiles) raise DictConsistencyError(msg, 103, variable.xmlfiles)
if self.when_not is not undefined: if self.when_not is not undefined:
msg = _('the variable "{0}" has an invalid attribute "{1}", "when" and "when_not" cannot set together').format(self.path, self.attribute_name) msg = _(
'the variable "{0}" has an invalid attribute "{1}", "when" and "when_not" cannot set together'
).format(self.path, self.attribute_name)
raise DictConsistencyError(msg, 31, variable.xmlfiles) raise DictConsistencyError(msg, 31, variable.xmlfiles)
when = self.when when = self.when
inverse = False inverse = False
elif self.when_not is not undefined: elif self.when_not is not undefined:
if self.version == "1.0": if self.version == "1.0":
msg = _('"when_not" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"').format(self.attribute_name, self.path) msg = _(
'"when_not" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"'
).format(self.attribute_name, self.path)
raise DictConsistencyError(msg, 104, variable.xmlfiles) raise DictConsistencyError(msg, 104, variable.xmlfiles)
when = self.when_not when = self.when_not
inverse = True inverse = True
@ -650,7 +797,7 @@ class VariablePropertyCalculation(_VariableCalculation):
params["when"] = when params["when"] = when
params["inverse"] = inverse params["inverse"] = inverse
params[None].insert(0, self.attribute_name) params[None].insert(0, self.attribute_name)
func = 'variable_to_property' func = "variable_to_property"
return { return {
"function": func, "function": func,
"params": params, "params": params,
@ -690,10 +837,14 @@ class InformationCalculation(Calculation):
) )
if variable is None: if variable is None:
if not objectspace.force_optional: if not objectspace.force_optional:
msg = _('cannot find variable "{0}" for the information "{1}" when calculating "{2}"').format(self.variable, self.information, self.attribute_name) msg = _(
'cannot find variable "{0}" for the information "{1}" when calculating "{2}"'
).format(self.variable, self.information, self.attribute_name)
raise DictConsistencyError(msg, 40, variable.xmlfiles) raise DictConsistencyError(msg, 40, variable.xmlfiles)
if identifier is not None: if identifier is not None:
msg = _('identifier not allowed for the information "{0}" when calculating "{1}"').format(self.information, self.attribute_name) msg = _(
'identifier not allowed for the information "{0}" when calculating "{1}"'
).format(self.information, self.attribute_name)
raise DictConsistencyError(msg, 41, variable.xmlfiles) raise DictConsistencyError(msg, 41, variable.xmlfiles)
if variable: if variable:
params[None][0]["variable"] = variable params[None][0]["variable"] = variable
@ -744,11 +895,15 @@ class IdentifierPropertyCalculation(_IdentifierCalculation):
objectspace, objectspace,
) -> dict: ) -> dict:
if self.version == "1.0": if self.version == "1.0":
msg = _('"when" is not allowed in format version 1.0 for attribute "{0}"').format(self.attribute_name) msg = _(
'"when" is not allowed in format version 1.0 for attribute "{0}"'
).format(self.attribute_name)
raise DictConsistencyError(msg, 105, variable.xmlfiles) raise DictConsistencyError(msg, 105, variable.xmlfiles)
if self.when is not undefined: if self.when is not undefined:
if self.when_not is not undefined: if self.when_not is not undefined:
msg = _('the identifier has an invalid attribute "{0}", "when" and "when_not" cannot set together').format(self.attribute_name) msg = _(
'the identifier has an invalid attribute "{0}", "when" and "when_not" cannot set together'
).format(self.attribute_name)
raise DictConsistencyError(msg, 35, variable.xmlfiles) raise DictConsistencyError(msg, 35, variable.xmlfiles)
when = self.when when = self.when
inverse = False inverse = False
@ -756,7 +911,9 @@ class IdentifierPropertyCalculation(_IdentifierCalculation):
when = self.when_not when = self.when_not
inverse = True inverse = True
else: else:
msg = _('the identifier has an invalid attribute "{0}", "when" and "when_not" cannot set together').format(self.attribute_name) msg = _(
'the identifier has an invalid attribute "{0}", "when" and "when_not" cannot set together'
).format(self.attribute_name)
raise DictConsistencyError raise DictConsistencyError
params = { params = {
None: [self.attribute_name, self.get_identifier()], None: [self.attribute_name, self.get_identifier()],
@ -779,7 +936,9 @@ class IndexCalculation(Calculation):
objectspace, objectspace,
) -> dict: ) -> dict:
if self.path not in objectspace.followers: if self.path not in objectspace.followers:
msg = _('the variable "{0}" is not a follower, so cannot have index type for "{1}"').format(self.path, self.attribute_name) msg = _(
'the variable "{0}" is not a follower, so cannot have index type for "{1}"'
).format(self.path, self.attribute_name)
raise DictConsistencyError(msg, 60, self.xmlfiles) raise DictConsistencyError(msg, 60, self.xmlfiles)
return { return {
"function": "calc_value", "function": "calc_value",
@ -809,7 +968,7 @@ CALCULATION_TYPES = {
"information": InformationCalculation, "information": InformationCalculation,
"variable": VariableCalculation, "variable": VariableCalculation,
"identifier": IdentifierCalculation, "identifier": IdentifierCalculation,
# FOR VERSION 1.0 # FOR VERSION 1.0
"suffix": IdentifierCalculation, "suffix": IdentifierCalculation,
"index": IndexCalculation, "index": IndexCalculation,
"namespace": NamespaceCalculation, "namespace": NamespaceCalculation,

View file

@ -37,17 +37,29 @@ from jinja2.sandbox import SandboxedEnvironment
from rougail.object_model import CONVERT_OPTION from rougail.object_model import CONVERT_OPTION
from rougail.error import display_xmlfiles from rougail.error import display_xmlfiles
from tiramisu import DynOptionDescription, calc_value, function_waiting_for_error from tiramisu import DynOptionDescription, calc_value, function_waiting_for_error
from tiramisu.error import ValueWarning, ConfigError, PropertiesOptionError, CancelParam, errors from tiramisu.error import (
ValueWarning,
ConfigError,
PropertiesOptionError,
CancelParam,
errors,
)
from .utils import normalize_family from .utils import normalize_family
from .i18n import _ from .i18n import _
ori_raise_carry_out_calculation_error = errors.raise_carry_out_calculation_error ori_raise_carry_out_calculation_error = errors.raise_carry_out_calculation_error
def raise_carry_out_calculation_error(subconfig, *args, **kwargs): def raise_carry_out_calculation_error(subconfig, *args, **kwargs):
try: try:
ori_raise_carry_out_calculation_error(subconfig, *args, **kwargs) ori_raise_carry_out_calculation_error(subconfig, *args, **kwargs)
except ConfigError as err: except ConfigError as err:
ymlfiles = subconfig.config_bag.context.get_values().get_information(subconfig, 'ymlfiles', []) ymlfiles = subconfig.config_bag.context.get_values().get_information(
raise ConfigError(_('{0} in {1}').format(err, display_xmlfiles(ymlfiles))) subconfig, "ymlfiles", []
)
raise ConfigError(_("{0} in {1}").format(err, display_xmlfiles(ymlfiles)))
errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error
@ -124,7 +136,7 @@ def kw_to_string(kw, root=None):
if root is None: if root is None:
path = name path = name
else: else:
path = root + '.' + name path = root + "." + name
if isinstance(data, dict): if isinstance(data, dict):
yield from kw_to_string(data, root=path) yield from kw_to_string(data, root=path)
else: else:
@ -172,11 +184,21 @@ def jinja_to_function(
except Exception as err: except Exception as err:
kw_str = ", ".join(kw_to_string(kw)) kw_str = ", ".join(kw_to_string(kw))
raise ConfigError( raise ConfigError(
_('cannot calculating "{0}" attribute for variable "{1}" in {2} with parameters "{3}": {4}').format(__internal_attribute, __internal_variable, display_xmlfiles(__internal_files), kw_str, err) _(
'cannot calculating "{0}" attribute for variable "{1}" in {2} with parameters "{3}": {4}'
).format(
__internal_attribute,
__internal_variable,
display_xmlfiles(__internal_files),
kw_str,
err,
)
) from err ) from err
convert = CONVERT_OPTION[__internal_type].get("func", str) convert = CONVERT_OPTION[__internal_type].get("func", str)
if __internal_multi: if __internal_multi:
values = [convert(val.strip()) for val in values.split("\n") if val.strip() != ""] values = [
convert(val.strip()) for val in values.split("\n") if val.strip() != ""
]
if not values and __default_value is not None: if not values and __default_value is not None:
return __default_value return __default_value
return values return values

View file

@ -290,9 +290,10 @@ class Common:
): ):
"""Populate variable parameters""" """Populate variable parameters"""
if not isinstance(param, dict): if not isinstance(param, dict):
param = {"type": "any", param = {
"value": param, "type": "any",
} "value": param,
}
if param["type"] == "value": if param["type"] == "value":
return f"ParamValue({param['value']})" return f"ParamValue({param['value']})"
if param["type"] == "information": if param["type"] == "information":
@ -331,9 +332,7 @@ class Common:
return f'ParamInformation("{param["information"]}", {default}, option={option_name})' return f'ParamInformation("{param["information"]}", {default}, option={option_name})'
else: else:
# if we want to get information from the a parent family # if we want to get information from the a parent family
information = ( information = f'ParamInformation("{param["information"]}", {default})'
f'ParamInformation("{param["information"]}", {default})'
)
information_name = self.tiramisu.get_information_name() information_name = self.tiramisu.get_information_name()
self.tiramisu.text["option"].append( self.tiramisu.text["option"].append(
f"{information_name} = {information}" f"{information_name} = {information}"

View file

@ -26,6 +26,7 @@ from rougail.utils import normalize_family, undefined
from tiramisu import Calculation from tiramisu import Calculation
from tiramisu.error import ( from tiramisu.error import (
PropertiesOptionError, PropertiesOptionError,
AttributeOptionError,
LeadershipError, LeadershipError,
ConfigError, ConfigError,
CancelParam, CancelParam,
@ -44,6 +45,7 @@ class UserDatas:
self.values = {} self.values = {}
self.errors = [] self.errors = []
self.warnings = [] self.warnings = []
self.show_secrets = False
self._populate_values(user_datas) self._populate_values(user_datas)
self._auto_configure_dynamics() self._auto_configure_dynamics()
self._populate_config() self._populate_config()
@ -113,7 +115,9 @@ class UserDatas:
continue continue
identifier = self._get_identifier(tconfig.name(), name) identifier = self._get_identifier(tconfig.name(), name)
if identifier != normalize_family(identifier): if identifier != normalize_family(identifier):
msg = _('cannot load variable path "{0}", the identifier "{1}" is not valid in {2}').format(path, identifier, data["source"]) msg = _(
'cannot load variable path "{0}", the identifier "{1}" is not valid in {2}'
).format(path, identifier, data["source"])
self.warnings.append(msg) self.warnings.append(msg)
continue continue
if identifier is None: if identifier is None:
@ -155,6 +159,27 @@ class UserDatas:
cache[current_path] = config, identifier cache[current_path] = config, identifier
break break
def convert_value(self, path, option, options, value):
# converted value
needs_convert = options.get("needs_convert", False)
if option.ismulti():
if options.get("multi_separator") and not isinstance(value, list):
value = value.split(options["multi_separator"])
self.values[path]["values"] = value
if option.issubmulti():
value = [[val] for val in value]
if needs_convert:
if option.issubmulti():
for idx, val in enumerate(value):
value[idx] = [convert_value(option, v) for v in val]
else:
value = [convert_value(option, val) for val in value]
self.values[path]["values"] = value
self.values[path]["options"]["needs_convert"] = False
elif needs_convert:
value = convert_value(option, value)
return value
def _populate_config(self): def _populate_config(self):
while self.values: while self.values:
value_is_set = False value_is_set = False
@ -173,33 +198,25 @@ class UserDatas:
).format(path, self.values[path]["source"]) ).format(path, self.values[path]["source"])
) )
continue continue
value = self.values[path]["values"] value = self.convert_value(
needs_convert = options.get("needs_convert", False) path, option, options, self.values[path]["values"]
)
# converted value
if option.ismulti():
if options.get("multi_separator") and not isinstance(value, list):
value = value.split(options["multi_separator"])
self.values[path]["values"] = value
if option.issubmulti():
value = [[val] for val in value]
if needs_convert:
if option.issubmulti():
for idx, val in enumerate(value):
value[idx] = [convert_value(option, v) for v in val]
else:
value = [convert_value(option, val) for val in value]
self.values[path]["values"] = value
self.values[path]["options"]["needs_convert"] = False
elif needs_convert:
value = convert_value(option, value)
index = option.index() index = option.index()
if index is not None: if index is not None:
if not isinstance(value, list) or index >= len(value): if not isinstance(value, list) or index >= len(value):
continue continue
value = value[index] value = value[index]
if option.isleader():
len_leader = len(option.value.get())
if len_leader:
for idx in range(len_leader - 1, -1, -1):
option.value.pop(idx)
try: try:
option.value.set(value) option.value.set(value)
option.information.set(
"loaded_from", _("loaded from {0}").format(options["source"])
)
value_is_set = True value_is_set = True
# value is correctly set, remove variable to the set # value is correctly set, remove variable to the set
if index is not None: if index is not None:
@ -224,33 +241,144 @@ class UserDatas:
return None return None
return finded[0] return finded[0]
def _display_value(self, option, value):
if not self.show_secrets and option.type() == "password":
return "*" * 10
return value
def _populate_error_warnings(self): def _populate_error_warnings(self):
# we don't find variable, apply value just to get error or warning messages # we don't find variable, apply value just to get error or warning messages
for path, data in self.values.items(): for path, options in self.values.items():
value = options["values"]
option = self.config.option(path)
try: try:
option = self.config.option(path)
value = data["values"]
if option.isoptiondescription(): if option.isoptiondescription():
if value: if value:
self.warnings.append( self.warnings.append(
_('the variable "{0}" is a family, so cannot set the value "{1}" in {2}').format( _(
option.path(), 'cannot set the value "{0}" to the family {1}, it will be ignored when loading from {2}'
value, ).format(
data["source"], self._display_value(option, value),
option.description(with_quote=True),
options["source"],
) )
) )
continue continue
if option.isfollower(): except AttributeOptionError as err:
for index, val in enumerate(value): if err.code == "option-not-found":
self.warnings.append(
_(
'variable or family "{0}" does not exist, it will be ignored when loading from {1}'
).format(err.path, options["source"])
)
elif err.code == "option-dynamic":
self.warnings.append(
_(
'"{0}" is the name of a dynamic family, it will be ignored when loading from {1}'
).format(option.description(with_quote=True), options["source"])
)
else:
self.warnings.append(
_("{0} loaded from {1}").format(err, options["source"])
)
continue
value = self.convert_value(
path, option, self.values[path].get("options", {}), value
)
if option.isfollower():
indexes = range(len(value))
else:
indexes = [None]
for index in indexes:
try:
if option.isfollower():
val = value[index]
if val is undefined or isinstance(val, CancelParam): if val is undefined or isinstance(val, CancelParam):
continue continue
self.config.option(path, index).value.set(val) self.config.option(path, index).value.set(val)
else: else:
option.value.set(value) option.value.set(value)
except AttributeError as err: except PropertiesOptionError as err:
self.warnings.append(_('{0} loaded from {1}').format(err, data["source"])) if err.code == "property-error":
except (ValueError, LeadershipError, PropertiesOptionError) as err: properties = err.display_properties(
self.warnings.append(_('{0} in {1}').format(err, data["source"])) force_property=True, add_quote=False
)
err_path = err._subconfig.path
display_name = option.description(with_quote=True)
if index is not None:
if path == err_path:
self.warnings.append(
_(
'variable {0} at index "{1}" is {2}, it will be ignored when loading from {3}'
).format(
display_name,
index,
properties,
options["source"],
)
)
else:
self.warnings.append(
_(
'family {0} is {1}, {2} at index "{3}" will be ignored when loading from {4}'
).format(
err._name,
properties,
display_name,
index,
options["source"],
)
)
else:
if path == err_path:
self.warnings.append(
_(
"variable {0} is {1}, it will be ignored when loading from {2}"
).format(
display_name, properties, options["source"]
)
)
else:
self.warnings.append(
_(
"family {0} is {1}, {2} will be ignored when loading from {3}"
).format(
err._name,
properties,
display_name,
options["source"],
)
)
else:
self.warnings.append(
_("{0} in {1}").format(err, options["source"])
)
except LeadershipError as err:
self.warnings.append(_("{0} in {1}").format(err, options["source"]))
except ValueError as err:
err.prefix = ""
if index is not None:
self.warnings.append(
_(
'the value "{0}" is invalid for {1} at index "{2}", {3}, it will be ignored when loading from {4}'
).format(
self._display_value(option, value),
option.description(with_quote=True),
err,
options["source"],
)
)
else:
self.warnings.append(
_(
'the value "{0}" is invalid for {1}, {2}, it will be ignored when loading from {3}'
).format(
self._display_value(option, value),
option.description(with_quote=True),
err,
options["source"],
)
)
def convert_value(option, value): def convert_value(option, value):
@ -265,5 +393,8 @@ def convert_value(option, value):
value = int(value) value = int(value)
func = CONVERT_OPTION.get(option_type, {}).get("func") func = CONVERT_OPTION.get(option_type, {}).get("func")
if func: if func:
return func(value) try:
return func(value)
except:
pass
return value return value

View file

@ -162,7 +162,13 @@ def get_jinja_variable_to_param(
for variable_path, data in founded_variables.items(): for variable_path, data in founded_variables.items():
yield data[1], data[0], variable_path yield data[1], data[0], variable_path
def calc_multi_for_type_variable(local_variable: 'Variable', variable_in_calculation_path: str, variable_in_calculation: 'Variable', objectspace: 'RougailConvert') -> Union[bool, str]:
def calc_multi_for_type_variable(
local_variable: "Variable",
variable_in_calculation_path: str,
variable_in_calculation: "Variable",
objectspace: "RougailConvert",
) -> Union[bool, str]:
variable_in_calculation_multi = variable_in_calculation.multi variable_in_calculation_multi = variable_in_calculation.multi
if local_variable.path in objectspace.families: if local_variable.path in objectspace.families:
# it's a family # it's a family
@ -171,33 +177,39 @@ def calc_multi_for_type_variable(local_variable: 'Variable', variable_in_calcula
local_variable_multi = local_variable.multi local_variable_multi = local_variable.multi
# variable is a leader # variable is a leader
if variable_in_calculation.path in objectspace.leaders: if variable_in_calculation.path in objectspace.leaders:
local_variable_parent = local_variable.path.rsplit('.', 1)[0] local_variable_parent = local_variable.path.rsplit(".", 1)[0]
variable_in_calculation_parent = variable_in_calculation.path.rsplit('.', 1)[0] variable_in_calculation_parent = variable_in_calculation.path.rsplit(
".", 1
)[0]
if local_variable_parent == variable_in_calculation_parent: if local_variable_parent == variable_in_calculation_parent:
variable_in_calculation_multi = False variable_in_calculation_multi = False
# variable is a follower # variable is a follower
elif variable_in_calculation.path in objectspace.followers: elif variable_in_calculation.path in objectspace.followers:
local_variable_parent = local_variable.path.rsplit('.', 1)[0] local_variable_parent = local_variable.path.rsplit(".", 1)[0]
variable_in_calculation_parent = variable_in_calculation.path.rsplit('.', 1)[0] variable_in_calculation_parent = variable_in_calculation.path.rsplit(
".", 1
)[0]
if local_variable_parent != variable_in_calculation_parent: if local_variable_parent != variable_in_calculation_parent:
if variable_in_calculation_multi: if variable_in_calculation_multi:
variable_in_calculation_multi = 'submulti' variable_in_calculation_multi = "submulti"
else: else:
variable_in_calculation_multi = True variable_in_calculation_multi = True
# variable is in a dynamic family # variable is in a dynamic family
if objectspace.paths.is_dynamic(variable_in_calculation.path): if objectspace.paths.is_dynamic(variable_in_calculation.path):
common_path = get_common_path(local_variable.path, variable_in_calculation_path) common_path = get_common_path(
local_variable.path, variable_in_calculation_path
)
common_variable_path = variable_in_calculation_path common_variable_path = variable_in_calculation_path
if common_path: if common_path:
common_variable_path = common_variable_path[len(common_path) + 1:] common_variable_path = common_variable_path[len(common_path) + 1 :]
count_identifiers = common_variable_path.count('{{ identifier }}') count_identifiers = common_variable_path.count("{{ identifier }}")
if count_identifiers == 1: if count_identifiers == 1:
if variable_in_calculation_multi is False: if variable_in_calculation_multi is False:
variable_in_calculation_multi = True variable_in_calculation_multi = True
else: else:
variable_in_calculation_multi = 'submulti' variable_in_calculation_multi = "submulti"
elif count_identifiers > 1: elif count_identifiers > 1:
variable_in_calculation_multi = 'submulti' variable_in_calculation_multi = "submulti"
return local_variable_multi, variable_in_calculation_multi return local_variable_multi, variable_in_calculation_multi

View file

@ -0,0 +1,22 @@
{
"rougail.leadership.leader": {
"owner": "default",
"value": [
"value_1",
"value_2",
"value_3"
]
},
"rougail.leadership.follower": {
"owner": [
"default",
"default",
"default"
],
"value": [
null,
null,
null
]
}
}

View file

@ -0,0 +1,16 @@
{
"rougail.leadership.leader": [
{
"rougail.leadership.leader": "value_1",
"rougail.leadership.follower": null
},
{
"rougail.leadership.leader": "value_2",
"rougail.leadership.follower": null
},
{
"rougail.leadership.leader": "value_3",
"rougail.leadership.follower": null
}
]
}

View file

@ -0,0 +1,22 @@
{
"rougail.leadership.leader": {
"owner": "default",
"value": [
"value_1",
"value_2",
"value_3"
]
},
"rougail.leadership.follower": {
"owner": [
"default",
"default",
"default"
],
"value": [
null,
null,
null
]
}
}

View file

@ -0,0 +1 @@
["rougail.leadership.follower", "rougail.leadership.follower", "rougail.leadership.follower"]

View file

@ -0,0 +1,16 @@
{
"rougail.leadership.leader": [
{
"rougail.leadership.leader": "value_1",
"rougail.leadership.follower": null
},
{
"rougail.leadership.leader": "value_2",
"rougail.leadership.follower": null
},
{
"rougail.leadership.leader": "value_3",
"rougail.leadership.follower": null
}
]
}

View file

@ -0,0 +1,17 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
try:
groups.namespace
except:
groups.addgroup('namespace')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_3 = StrOption(name="leader", doc="a leader", multi=True, default=["value_1", "value_2", "value_3"], properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml'], 'type': 'string', 'test': ('val1', 'val2')})
option_4 = StrOption(name="follower", doc="a follower", multi=True, properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml'], 'type': 'string'})
optiondescription_2 = Leadership(name="leadership", doc="a leadership", children=[option_3, option_4], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml']})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[optiondescription_2], properties=frozenset({"basic"}), informations={'ymlfiles': ['']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,12 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_2 = StrOption(name="leader", doc="a leader", multi=True, default=["value_1", "value_2", "value_3"], properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml'], 'type': 'string', 'test': ('val1', 'val2')})
option_3 = StrOption(name="follower", doc="a follower", multi=True, properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml'], 'type': 'string'})
optiondescription_1 = Leadership(name="leadership", doc="a leadership", children=[option_2, option_3], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/40_0leadership_reduce/rougail/00-base.yml']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -12,7 +12,7 @@
"default" "default"
], ],
"value": [ "value": [
"cannot access to option \"a follower\" because has property \"disabled\" (the value of \"leader\" is \"a\")", "cannot access to option \"a follower\" at index \"0\" because has property \"disabled\" (the value of \"leader\" is \"a\")",
"b" "b"
] ]
} }

View file

@ -12,7 +12,7 @@
"default" "default"
], ],
"value": [ "value": [
"cannot access to option \"a follower\" because has property \"disabled\" (the value of \"leader\" is \"a\")", "cannot access to option \"a follower\" at index \"0\" because has property \"disabled\" (the value of \"leader\" is \"a\")",
"b" "b"
] ]
} }

View file

@ -31,7 +31,7 @@ excludes = set([])
# excludes = set(['60_5family_dynamic_variable_outside_sub_suffix']) # excludes = set(['60_5family_dynamic_variable_outside_sub_suffix'])
test_ok -= excludes test_ok -= excludes
# test_ok = ['04_5validators_multi3'] test_ok = ['44_9calculated_default_leadership_leader']
test_ok = list(test_ok) test_ok = list(test_ok)