fix: black
This commit is contained in:
parent
29453523b2
commit
e77355cbc5
17 changed files with 658 additions and 370 deletions
|
|
@ -79,7 +79,7 @@ class Annotator(Walk):
|
||||||
def check_sequence(self) -> None:
|
def check_sequence(self) -> None:
|
||||||
"""No subfamily in a sequence"""
|
"""No subfamily in a sequence"""
|
||||||
for family in self.get_families():
|
for family in self.get_families():
|
||||||
if family.type == 'leadership':
|
if family.type == "leadership":
|
||||||
family.type = "sequence"
|
family.type = "sequence"
|
||||||
if family.type != "sequence":
|
if family.type != "sequence":
|
||||||
continue
|
continue
|
||||||
|
|
@ -113,7 +113,9 @@ class Annotator(Walk):
|
||||||
)
|
)
|
||||||
self.objectspace.informations.add(family.path, "dynamic_variable", path)
|
self.objectspace.informations.add(family.path, "dynamic_variable", path)
|
||||||
if family.xmlfiles:
|
if family.xmlfiles:
|
||||||
self.objectspace.informations.add(family.path, "ymlfiles", family.xmlfiles)
|
self.objectspace.informations.add(
|
||||||
|
family.path, "ymlfiles", family.xmlfiles
|
||||||
|
)
|
||||||
|
|
||||||
def set_modes(self):
|
def set_modes(self):
|
||||||
if self.objectspace.modes_level:
|
if self.objectspace.modes_level:
|
||||||
|
|
@ -130,8 +132,12 @@ class Annotator(Walk):
|
||||||
modes = self.modes = {
|
modes = self.modes = {
|
||||||
name: Mode(idx) for idx, name in enumerate(self.objectspace.modes_level)
|
name: Mode(idx) for idx, name in enumerate(self.objectspace.modes_level)
|
||||||
}
|
}
|
||||||
default_variable_mode = self.default_variable_mode = self.objectspace.default_variable_mode
|
default_variable_mode = self.default_variable_mode = (
|
||||||
default_family_mode = self.default_family_mode = self.objectspace.default_family_mode
|
self.objectspace.default_variable_mode
|
||||||
|
)
|
||||||
|
default_family_mode = self.default_family_mode = (
|
||||||
|
self.objectspace.default_family_mode
|
||||||
|
)
|
||||||
list_modes = list(modes)
|
list_modes = list(modes)
|
||||||
if default_variable_mode not in list_modes:
|
if default_variable_mode not in list_modes:
|
||||||
msg = _(
|
msg = _(
|
||||||
|
|
@ -177,7 +183,9 @@ class Annotator(Walk):
|
||||||
if self.has_mode(obj):
|
if self.has_mode(obj):
|
||||||
msg = _(
|
msg = _(
|
||||||
'mode "{0}" for "{1}" is not a valid mode, valid modes are {2}'
|
'mode "{0}" for "{1}" is not a valid mode, valid modes are {2}'
|
||||||
).format(obj.mode, obj.name, display_list(list(self.modes), add_quote=True))
|
).format(
|
||||||
|
obj.mode, obj.name, display_list(list(self.modes), add_quote=True)
|
||||||
|
)
|
||||||
raise DictConsistencyError(msg, 71, obj.xmlfiles)
|
raise DictConsistencyError(msg, 71, obj.xmlfiles)
|
||||||
elif self.has_mode(obj) and obj.mode not in self.modes:
|
elif self.has_mode(obj) and obj.mode not in self.modes:
|
||||||
msg = _(
|
msg = _(
|
||||||
|
|
|
||||||
|
|
@ -173,9 +173,7 @@ class Annotator(Walk):
|
||||||
for tag in variable.tags:
|
for tag in variable.tags:
|
||||||
self.check_tag(tag, variable.xmlfiles)
|
self.check_tag(tag, variable.xmlfiles)
|
||||||
self.objectspace.properties.add(variable.path, tag, True)
|
self.objectspace.properties.add(variable.path, tag, True)
|
||||||
self.objectspace.informations.add(
|
self.objectspace.informations.add(variable.path, "tags", tuple(variable.tags))
|
||||||
variable.path, "tags", tuple(variable.tags)
|
|
||||||
)
|
|
||||||
|
|
||||||
def check_tag(
|
def check_tag(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,7 @@ class Annotator(Walk): # pylint: disable=R0903
|
||||||
'the variable "{0}" has attribute "secret_manager" so must not have default value'
|
'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)
|
||||||
self.objectspace.informations.add(
|
self.objectspace.informations.add(path, "secret_manager", True)
|
||||||
path, "secret_manager", True
|
|
||||||
)
|
|
||||||
|
|
||||||
def convert_variable(self):
|
def convert_variable(self):
|
||||||
"""convert variable"""
|
"""convert variable"""
|
||||||
|
|
@ -214,9 +212,9 @@ class Annotator(Walk): # pylint: disable=R0903
|
||||||
if variable.type is not None:
|
if variable.type is not None:
|
||||||
return
|
return
|
||||||
## choice type inference from the `choices` attribute
|
## choice type inference from the `choices` attribute
|
||||||
#if variable.choices is not None:
|
# if variable.choices is not None:
|
||||||
# variable.type = "choice"
|
# variable.type = "choice"
|
||||||
#elif variable.regexp is not None:
|
# elif variable.regexp is not None:
|
||||||
# variable.type = "regexp"
|
# variable.type = "regexp"
|
||||||
if variable.default not in [None, []]:
|
if variable.default not in [None, []]:
|
||||||
if isinstance(variable.default, list):
|
if isinstance(variable.default, list):
|
||||||
|
|
@ -253,7 +251,9 @@ class Annotator(Walk): # pylint: disable=R0903
|
||||||
self._convert_variable_multi(calculated_variable)
|
self._convert_variable_multi(calculated_variable)
|
||||||
identifier_is_a_calculation = False
|
identifier_is_a_calculation = False
|
||||||
if isinstance(variable.default, Calculation):
|
if isinstance(variable.default, Calculation):
|
||||||
identifier_is_a_calculation = isinstance(variable.default.identifier, Calculation)
|
identifier_is_a_calculation = isinstance(
|
||||||
|
variable.default.identifier, Calculation
|
||||||
|
)
|
||||||
variable.multi = calc_multi_for_type_variable(
|
variable.multi = calc_multi_for_type_variable(
|
||||||
variable,
|
variable,
|
||||||
calculated_variable_path,
|
calculated_variable_path,
|
||||||
|
|
@ -317,11 +317,11 @@ class Annotator(Walk): # pylint: disable=R0903
|
||||||
self.objectspace.multis[variable.path] = "submulti"
|
self.objectspace.multis[variable.path] = "submulti"
|
||||||
elif variable.multi:
|
elif variable.multi:
|
||||||
self.objectspace.multis[variable.path] = True
|
self.objectspace.multis[variable.path] = True
|
||||||
# if variable.regexp is not None and variable.type != "regexp":
|
# if variable.regexp is not None and variable.type != "regexp":
|
||||||
# msg = _(
|
# msg = _(
|
||||||
# 'the variable "{0}" has regexp attribut but has not the "regexp" type'
|
# 'the variable "{0}" has regexp attribut but has not the "regexp" type'
|
||||||
# ).format(variable.path)
|
# ).format(variable.path)
|
||||||
# raise DictConsistencyError(msg, 37, variable.xmlfiles)
|
# raise DictConsistencyError(msg, 37, variable.xmlfiles)
|
||||||
if variable.mandatory is None:
|
if variable.mandatory is None:
|
||||||
variable.mandatory = True
|
variable.mandatory = True
|
||||||
|
|
||||||
|
|
@ -358,9 +358,9 @@ class Annotator(Walk): # pylint: disable=R0903
|
||||||
def verify_choices(self):
|
def verify_choices(self):
|
||||||
for variable in self.get_variables():
|
for variable in self.get_variables():
|
||||||
# FIXME
|
# FIXME
|
||||||
# if variable.type is None and variable.choices:
|
# if variable.type is None and variable.choices:
|
||||||
# # choice type inference from the `choices` attribute
|
# # choice type inference from the `choices` attribute
|
||||||
# variable.type = "choice"
|
# variable.type = "choice"
|
||||||
if variable.type != "choice":
|
if variable.type != "choice":
|
||||||
continue
|
continue
|
||||||
if variable.default is None:
|
if variable.default is None:
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,7 @@ class _RougailConfig:
|
||||||
self.generate_config()
|
self.generate_config()
|
||||||
config = self.config.config.copy()
|
config = self.config.config.copy()
|
||||||
config.value.importation(self.config.value.exportation())
|
config.value.importation(self.config.value.exportation())
|
||||||
config.property.importation(
|
config.property.importation(self.config.property.exportation())
|
||||||
self.config.property.exportation()
|
|
||||||
)
|
|
||||||
config.property.read_only()
|
config.property.read_only()
|
||||||
if backward_compatibility is None:
|
if backward_compatibility is None:
|
||||||
backward_compatibility = self.backward_compatibility
|
backward_compatibility = self.backward_compatibility
|
||||||
|
|
@ -250,7 +248,7 @@ class StaticRougailConvert(RougailConvert):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
add_extra_options: bool,
|
add_extra_options: bool,
|
||||||
rougailconfig: dict={},
|
rougailconfig: dict = {},
|
||||||
) -> None:
|
) -> None:
|
||||||
self.add_extra_options = add_extra_options
|
self.add_extra_options = add_extra_options
|
||||||
super().__init__(rougailconfig)
|
super().__init__(rougailconfig)
|
||||||
|
|
@ -434,10 +432,11 @@ secret_manager: # {_("The secret manager")}
|
||||||
"user data": [],
|
"user data": [],
|
||||||
"output": [],
|
"output": [],
|
||||||
}
|
}
|
||||||
processes_tr = {"structural": _("structural"),
|
processes_tr = {
|
||||||
"user data": _("user data"),
|
"structural": _("structural"),
|
||||||
"output": _("output"),
|
"user data": _("user data"),
|
||||||
}
|
"output": _("output"),
|
||||||
|
}
|
||||||
processes_empty = []
|
processes_empty = []
|
||||||
for module in get_sub_modules().values():
|
for module in get_sub_modules().values():
|
||||||
data = module.get_rougail_config(backward_compatibility=backward_compatibility)
|
data = module.get_rougail_config(backward_compatibility=backward_compatibility)
|
||||||
|
|
@ -495,7 +494,9 @@ secret_manager: # {_("The secret manager")}
|
||||||
"NAME", hidden_output
|
"NAME", hidden_output
|
||||||
)
|
)
|
||||||
rougail_process += f""" description: {_('outputs {0} did not allow user data')}
|
rougail_process += f""" description: {_('outputs {0} did not allow user data')}
|
||||||
""".format(display_list(hidden_outputs, add_quote=True, separator="or"))
|
""".format(
|
||||||
|
display_list(hidden_outputs, add_quote=True, separator="or")
|
||||||
|
)
|
||||||
elif objects:
|
elif objects:
|
||||||
rougail_process += " default: {DEFAULT}".format(
|
rougail_process += " default: {DEFAULT}".format(
|
||||||
DEFAULT=objects[0]["name"]
|
DEFAULT=objects[0]["name"]
|
||||||
|
|
@ -557,7 +558,9 @@ def _rougail_config(
|
||||||
backward_compatibility: bool = True,
|
backward_compatibility: bool = True,
|
||||||
add_extra_options: bool = True,
|
add_extra_options: bool = True,
|
||||||
) -> "OptionDescription":
|
) -> "OptionDescription":
|
||||||
processes, processes_empty, rougail_options = get_common_rougail_config(backward_compatibility=backward_compatibility)
|
processes, processes_empty, rougail_options = get_common_rougail_config(
|
||||||
|
backward_compatibility=backward_compatibility
|
||||||
|
)
|
||||||
convert = StaticRougailConvert(add_extra_options)
|
convert = StaticRougailConvert(add_extra_options)
|
||||||
convert.init()
|
convert.init()
|
||||||
convert.namespace = None
|
convert.namespace = None
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,16 @@ class Rougail(UserData):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
rougailconfig: Optional[RougailConfig]=None,
|
rougailconfig: Optional[RougailConfig] = None,
|
||||||
load_from_tiramisu_cache: bool=False,
|
load_from_tiramisu_cache: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
if rougailconfig is None:
|
if rougailconfig is None:
|
||||||
rougailconfig = RougailConfig
|
rougailconfig = RougailConfig
|
||||||
self.rougailconfig = rougailconfig
|
self.rougailconfig = rougailconfig
|
||||||
self.load_from_tiramisu_cache = load_from_tiramisu_cache and Path(self.rougailconfig["tiramisu_cache"]).is_file()
|
self.load_from_tiramisu_cache = (
|
||||||
|
load_from_tiramisu_cache
|
||||||
|
and Path(self.rougailconfig["tiramisu_cache"]).is_file()
|
||||||
|
)
|
||||||
types = rougail_type(self.rougailconfig)
|
types = rougail_type(self.rougailconfig)
|
||||||
if not self.load_from_tiramisu_cache:
|
if not self.load_from_tiramisu_cache:
|
||||||
self.converted = RougailConvert(self.rougailconfig, **types)
|
self.converted = RougailConvert(self.rougailconfig, **types)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ details.
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
|
@ -104,10 +105,16 @@ class CollectFamily:
|
||||||
new_parameters = {}
|
new_parameters = {}
|
||||||
children = self.parameters
|
children = self.parameters
|
||||||
# when an attribute starts with "_", the variable name without this "_" is a variable
|
# when an attribute starts with "_", the variable name without this "_" is a variable
|
||||||
sub_variables = [key[1:] for key in self.parameters if key.startswith('_') and key[1:] in self.parameters]
|
sub_variables = [
|
||||||
|
key[1:]
|
||||||
|
for key in self.parameters
|
||||||
|
if key.startswith("_") and key[1:] in self.parameters
|
||||||
|
]
|
||||||
# and known variables
|
# and known variables
|
||||||
if self.test_exists and self.path in self.objectspace.paths:
|
if self.test_exists and self.path in self.objectspace.paths:
|
||||||
sub_variables.extend([p.rsplit('.', 1)[-1] for p in self.objectspace.parents[self.path]])
|
sub_variables.extend(
|
||||||
|
[p.rsplit(".", 1)[-1] for p in self.objectspace.parents[self.path]]
|
||||||
|
)
|
||||||
attributes = self.object["attrs"]
|
attributes = self.object["attrs"]
|
||||||
attributes_types = self.object["attributes_types"]
|
attributes_types = self.object["attributes_types"]
|
||||||
if self.types:
|
if self.types:
|
||||||
|
|
@ -127,10 +134,12 @@ class CollectFamily:
|
||||||
children.pop(key)
|
children.pop(key)
|
||||||
else:
|
else:
|
||||||
new_parameters[key[1:]] = children.pop(key)
|
new_parameters[key[1:]] = children.pop(key)
|
||||||
elif key in types_children or \
|
elif (
|
||||||
key not in attributes or \
|
key in types_children
|
||||||
key in sub_variables or \
|
or key not in attributes
|
||||||
not self.parameter_is_an_attributes(key, value, attributes_types):
|
or key in sub_variables
|
||||||
|
or not self.parameter_is_an_attributes(key, value, attributes_types)
|
||||||
|
):
|
||||||
if key == "type" and self.types and key not in types_children:
|
if key == "type" and self.types and key not in types_children:
|
||||||
children.pop(key)
|
children.pop(key)
|
||||||
else:
|
else:
|
||||||
|
|
@ -227,6 +236,7 @@ class CollectVariable:
|
||||||
secret_manager,
|
secret_manager,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CollectType:
|
class CollectType:
|
||||||
"""Determine the option type
|
"""Determine the option type
|
||||||
1/ self.option_type must be "variable" or "family" option type
|
1/ self.option_type must be "variable" or "family" option type
|
||||||
|
|
@ -250,7 +260,12 @@ class CollectType:
|
||||||
self.variable_in_sequence()
|
self.variable_in_sequence()
|
||||||
self.family_or_variable()
|
self.family_or_variable()
|
||||||
if self.user_type:
|
if self.user_type:
|
||||||
logging.info("family_or_variable: %s is a %s (%s)", self.path, self.option_type, self.user_type)
|
logging.info(
|
||||||
|
"family_or_variable: %s is a %s (%s)",
|
||||||
|
self.path,
|
||||||
|
self.option_type,
|
||||||
|
self.user_type,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logging.info("family_or_variable: %s is a %s", self.path, self.option_type)
|
logging.info("family_or_variable: %s is a %s", self.path, self.option_type)
|
||||||
|
|
||||||
|
|
@ -259,18 +274,24 @@ class CollectType:
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check 'type' attributes and determine the option type"""
|
"""Check 'type' attributes and determine the option type"""
|
||||||
for type_name in ["_type", "type"]:
|
for type_name in ["_type", "type"]:
|
||||||
if type_name not in self.parameters or not isinstance(self.parameters[type_name], str):
|
if type_name not in self.parameters or not isinstance(
|
||||||
|
self.parameters[type_name], str
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
self.user_type = self.parameters[type_name]
|
self.user_type = self.parameters[type_name]
|
||||||
if self.user_type in self.objectspace.custom_family_types:
|
if self.user_type in self.objectspace.custom_family_types:
|
||||||
self.set_custom_type(self.objectspace.custom_family_types[self.user_type])
|
self.set_custom_type(
|
||||||
|
self.objectspace.custom_family_types[self.user_type]
|
||||||
|
)
|
||||||
if self.user_type is None:
|
if self.user_type is None:
|
||||||
self.object = self.objectspace.family_objects[-1]
|
self.object = self.objectspace.family_objects[-1]
|
||||||
else:
|
else:
|
||||||
self.set_object_user_type_family()
|
self.set_object_user_type_family()
|
||||||
break
|
break
|
||||||
elif self.user_type in self.objectspace.custom_variable_types:
|
elif self.user_type in self.objectspace.custom_variable_types:
|
||||||
self.set_custom_type(self.objectspace.custom_variable_types[self.user_type])
|
self.set_custom_type(
|
||||||
|
self.objectspace.custom_variable_types[self.user_type]
|
||||||
|
)
|
||||||
if self.user_type is None:
|
if self.user_type is None:
|
||||||
self.object = self.objectspace.variable_objects[0]
|
self.object = self.objectspace.variable_objects[0]
|
||||||
else:
|
else:
|
||||||
|
|
@ -281,11 +302,13 @@ class CollectType:
|
||||||
if not self.object:
|
if not self.object:
|
||||||
self.set_object_user_type_variable()
|
self.set_object_user_type_variable()
|
||||||
if self.raises and not self.object:
|
if self.raises and not self.object:
|
||||||
msg = _('cannot determine the type of the {0} "{1}"').format(self.user_type, self.path)
|
msg = _('cannot determine the type of the {0} "{1}"').format(
|
||||||
|
self.user_type, self.path
|
||||||
|
)
|
||||||
raise DictConsistencyError(msg, 43, self.sources)
|
raise DictConsistencyError(msg, 43, self.sources)
|
||||||
break
|
break
|
||||||
|
|
||||||
def set_custom_type(self, custom: dict, from_parent: bool=False) -> None:
|
def set_custom_type(self, custom: dict, from_parent: bool = False) -> None:
|
||||||
if self.raises and self.test_exists and self.path in self.objectspace.paths:
|
if self.raises and self.test_exists and self.path in self.objectspace.paths:
|
||||||
msg = f'cannot redefine "{self.path}" object to a custom type'
|
msg = f'cannot redefine "{self.path}" object to a custom type'
|
||||||
raise DictConsistencyError(msg, 64, self.sources)
|
raise DictConsistencyError(msg, 64, self.sources)
|
||||||
|
|
@ -302,7 +325,11 @@ class CollectType:
|
||||||
self.user_type = self.types.user_type
|
self.user_type = self.types.user_type
|
||||||
self.sources = self.types.sources + self.sources
|
self.sources = self.types.sources + self.sources
|
||||||
self.object = self.types.object
|
self.object = self.types.object
|
||||||
if not from_parent and self.option_type == "variable" and "type" in self.parameters:
|
if (
|
||||||
|
not from_parent
|
||||||
|
and self.option_type == "variable"
|
||||||
|
and "type" in self.parameters
|
||||||
|
):
|
||||||
self.parameters.pop("type")
|
self.parameters.pop("type")
|
||||||
|
|
||||||
def set_object_user_type_family(self):
|
def set_object_user_type_family(self):
|
||||||
|
|
@ -323,7 +350,9 @@ class CollectType:
|
||||||
if self.user_type:
|
if self.user_type:
|
||||||
return
|
return
|
||||||
for type_name in ["_dynamic", "dynamic"]:
|
for type_name in ["_dynamic", "dynamic"]:
|
||||||
if type_name in self.parameters and isinstance(self.parameters[type_name], (list, dict)):
|
if type_name in self.parameters and isinstance(
|
||||||
|
self.parameters[type_name], (list, dict)
|
||||||
|
):
|
||||||
self.user_type = "dynamic"
|
self.user_type = "dynamic"
|
||||||
self.option_type = "family"
|
self.option_type = "family"
|
||||||
break
|
break
|
||||||
|
|
@ -333,7 +362,9 @@ class CollectType:
|
||||||
return
|
return
|
||||||
# it's already a variable or a family
|
# it's already a variable or a family
|
||||||
old_option_type = self.option_type if self.user_type else None
|
old_option_type = self.option_type if self.user_type else None
|
||||||
self.option_type = "family" if self.path in self.objectspace.families else "variable"
|
self.option_type = (
|
||||||
|
"family" if self.path in self.objectspace.families else "variable"
|
||||||
|
)
|
||||||
if self.raises and old_option_type and self.option_type != old_option_type:
|
if self.raises and old_option_type and self.option_type != old_option_type:
|
||||||
msg = f'the {old_option_type} "{self.path}" is redefine as a {self.option_type}, which is not allowed'
|
msg = f'the {old_option_type} "{self.path}" is redefine as a {self.option_type}, which is not allowed'
|
||||||
raise DictConsistencyError(msg, 11, self.sources)
|
raise DictConsistencyError(msg, 11, self.sources)
|
||||||
|
|
@ -382,7 +413,9 @@ class CollectType:
|
||||||
def find_variable_object(self) -> bool:
|
def find_variable_object(self) -> bool:
|
||||||
attrs = set(self.parameters)
|
attrs = set(self.parameters)
|
||||||
for variable in self.objectspace.variable_objects:
|
for variable in self.objectspace.variable_objects:
|
||||||
if not attrs - variable["attrs"] and self.check_variable_parameters(variable):
|
if not attrs - variable["attrs"] and self.check_variable_parameters(
|
||||||
|
variable
|
||||||
|
):
|
||||||
self.option_type = "variable"
|
self.option_type = "variable"
|
||||||
self.check_no_extra_keys = True
|
self.check_no_extra_keys = True
|
||||||
self.object = variable
|
self.object = variable
|
||||||
|
|
@ -399,22 +432,39 @@ class CollectType:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def parameter_is_an_attributes(self, key: str, value: Any, attributes_types: dict) -> bool:
|
def parameter_is_an_attributes(
|
||||||
|
self, key: str, value: Any, attributes_types: dict
|
||||||
|
) -> bool:
|
||||||
if value is None:
|
if value is None:
|
||||||
return True
|
return True
|
||||||
if key in attributes_types["literals"] and value in attributes_types["literals"][key]:
|
if (
|
||||||
|
key in attributes_types["literals"]
|
||||||
|
and value in attributes_types["literals"][key]
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
for k, typ in [("strings", str), ("booleans", bool), ("integers", int), ("floats", float)]:
|
for k, typ in [
|
||||||
|
("strings", str),
|
||||||
|
("booleans", bool),
|
||||||
|
("integers", int),
|
||||||
|
("floats", float),
|
||||||
|
]:
|
||||||
if key in attributes_types[k] and isinstance(value, typ):
|
if key in attributes_types[k] and isinstance(value, typ):
|
||||||
return True
|
return True
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
if key in attributes_types["calculation"]:
|
if key in attributes_types["calculation"]:
|
||||||
return self.is_calculation(key, value, attributes_types=attributes_types)
|
return self.is_calculation(
|
||||||
|
key, value, attributes_types=attributes_types
|
||||||
|
)
|
||||||
if key in attributes_types["params"]:
|
if key in attributes_types["params"]:
|
||||||
return True
|
return True
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
current_value = value.copy()
|
current_value = value.copy()
|
||||||
for k, typ in [("strings", str), ("booleans", bool), ("integers", int), ("floats", float)]:
|
for k, typ in [
|
||||||
|
("strings", str),
|
||||||
|
("booleans", bool),
|
||||||
|
("integers", int),
|
||||||
|
("floats", float),
|
||||||
|
]:
|
||||||
if key in attributes_types["lists"][k]:
|
if key in attributes_types["lists"][k]:
|
||||||
for idx, val in reversed(list(enumerate(current_value))):
|
for idx, val in reversed(list(enumerate(current_value))):
|
||||||
if val is not None and not isinstance(val, typ):
|
if val is not None and not isinstance(val, typ):
|
||||||
|
|
@ -424,7 +474,9 @@ class CollectType:
|
||||||
return True
|
return True
|
||||||
if key in attributes_types["lists"]["calculation"]:
|
if key in attributes_types["lists"]["calculation"]:
|
||||||
for val in current_value:
|
for val in current_value:
|
||||||
if isinstance(val, dict) and not self.is_calculation(key, val, inside_list=True, attributes_types=attributes_types):
|
if isinstance(val, dict) and not self.is_calculation(
|
||||||
|
key, val, inside_list=True, attributes_types=attributes_types
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -440,8 +492,8 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
comment: Optional[str],
|
comment: Optional[str],
|
||||||
parent_option: Optional["Collect"],
|
parent_option: Optional["Collect"],
|
||||||
*,
|
*,
|
||||||
raises: bool=True,
|
raises: bool = True,
|
||||||
test_exists: bool=True,
|
test_exists: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.sources_types = None
|
self.sources_types = None
|
||||||
self.types = None
|
self.types = None
|
||||||
|
|
@ -464,14 +516,23 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
self.sources = objectspace.sources.copy()
|
self.sources = objectspace.sources.copy()
|
||||||
self.user_type = None
|
self.user_type = None
|
||||||
self.option_type = None
|
self.option_type = None
|
||||||
if parent_option is not None and parent_option.types is not None and self.name in parent_option.types.children:
|
if (
|
||||||
self.set_custom_type(parent_option.types.children[self.name], from_parent=True)
|
parent_option is not None
|
||||||
|
and parent_option.types is not None
|
||||||
|
and self.name in parent_option.types.children
|
||||||
|
):
|
||||||
|
self.set_custom_type(
|
||||||
|
parent_option.types.children[self.name], from_parent=True
|
||||||
|
)
|
||||||
self.check_no_extra_keys = False
|
self.check_no_extra_keys = False
|
||||||
if self.test_exists and path in objectspace.paths:
|
if self.test_exists and path in objectspace.paths:
|
||||||
for source in reversed(self.objectspace.paths[path].xmlfiles):
|
for source in reversed(self.objectspace.paths[path].xmlfiles):
|
||||||
self.sources.insert(0, source)
|
self.sources.insert(0, source)
|
||||||
if parent_option:
|
if parent_option:
|
||||||
self.family_is_sequence = parent_option.user_type in ["leadership", "sequence"]
|
self.family_is_sequence = parent_option.user_type in [
|
||||||
|
"leadership",
|
||||||
|
"sequence",
|
||||||
|
]
|
||||||
self.family_is_dynamic = parent_option.family_is_dynamic
|
self.family_is_dynamic = parent_option.family_is_dynamic
|
||||||
self.parent_dynamic = parent_option.parent_dynamic
|
self.parent_dynamic = parent_option.parent_dynamic
|
||||||
else:
|
else:
|
||||||
|
|
@ -509,7 +570,9 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
if self.raises:
|
if self.raises:
|
||||||
raise DictConsistencyError(
|
raise DictConsistencyError(
|
||||||
_('the {0} "{1}" has an invalid "{2}": {3}').format(self.option_type, self.path, key, err),
|
_('the {0} "{1}" has an invalid "{2}": {3}').format(
|
||||||
|
self.option_type, self.path, key, err
|
||||||
|
),
|
||||||
84,
|
84,
|
||||||
self.sources,
|
self.sources,
|
||||||
) from err
|
) from err
|
||||||
|
|
@ -536,17 +599,21 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
f"at index {idx}: {err}"
|
f"at index {idx}: {err}"
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
def is_dict(self, key: str, value: Any, *, attributes_types: Optional[dict]=None) -> bool:
|
def is_dict(
|
||||||
|
self, key: str, value: Any, *, attributes_types: Optional[dict] = None
|
||||||
|
) -> bool:
|
||||||
"""it's a dict, so it's a new variables!"""
|
"""it's a dict, so it's a new variables!"""
|
||||||
return isinstance(value, dict) and not self.is_calculation(key, value, attributes_types=attributes_types)
|
return isinstance(value, dict) and not self.is_calculation(
|
||||||
|
key, value, attributes_types=attributes_types
|
||||||
|
)
|
||||||
|
|
||||||
def is_calculation(
|
def is_calculation(
|
||||||
self,
|
self,
|
||||||
attribute: str,
|
attribute: str,
|
||||||
value: dict,
|
value: dict,
|
||||||
*,
|
*,
|
||||||
attributes_types: Optional[dict]=None,
|
attributes_types: Optional[dict] = None,
|
||||||
inside_list: bool=False,
|
inside_list: bool = False,
|
||||||
):
|
):
|
||||||
"""Check if it's a calculation"""
|
"""Check if it's a calculation"""
|
||||||
if not isinstance(value, dict):
|
if not isinstance(value, dict):
|
||||||
|
|
@ -603,11 +670,16 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
calculation_object["namespace"] = namespace
|
calculation_object["namespace"] = namespace
|
||||||
calculation_object["xmlfiles"] = self.sources
|
calculation_object["xmlfiles"] = self.sources
|
||||||
#
|
#
|
||||||
self.set_identifier_calculation_in_default_attribut(attribute, calculation_object, inside_list, index)
|
self.set_identifier_calculation_in_default_attribut(
|
||||||
|
attribute, calculation_object, inside_list, index
|
||||||
|
)
|
||||||
self.set_params_calculation(calculation_object, attribute)
|
self.set_params_calculation(calculation_object, attribute)
|
||||||
#
|
#
|
||||||
return_type = calculation_object.get("return_type")
|
return_type = calculation_object.get("return_type")
|
||||||
if return_type and return_type not in self.objectspace.variable_objects[0]["types"]:
|
if (
|
||||||
|
return_type
|
||||||
|
and return_type not in self.objectspace.variable_objects[0]["types"]
|
||||||
|
):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f'unknown "return_type" in {attribute} of variable "{self.path}"'
|
f'unknown "return_type" in {attribute} of variable "{self.path}"'
|
||||||
)
|
)
|
||||||
|
|
@ -624,7 +696,13 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
else:
|
else:
|
||||||
obj[attribute][index] = calc
|
obj[attribute][index] = calc
|
||||||
|
|
||||||
def set_identifier_calculation_in_default_attribut(self, attribute: str, calculation_object: dict, inside_list: bool, index: Optional[int]) -> None:
|
def set_identifier_calculation_in_default_attribut(
|
||||||
|
self,
|
||||||
|
attribute: str,
|
||||||
|
calculation_object: dict,
|
||||||
|
inside_list: bool,
|
||||||
|
index: Optional[int],
|
||||||
|
) -> None:
|
||||||
if attribute != "default" or "identifier" not in calculation_object:
|
if attribute != "default" or "identifier" not in calculation_object:
|
||||||
return
|
return
|
||||||
identifier = calculation_object["identifier"]
|
identifier = calculation_object["identifier"]
|
||||||
|
|
@ -634,7 +712,13 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
attributes_types=self.objectspace.variable_objects[0]["attributes_types"],
|
attributes_types=self.objectspace.variable_objects[0]["attributes_types"],
|
||||||
inside_list=inside_list,
|
inside_list=inside_list,
|
||||||
):
|
):
|
||||||
self.set_calculation("identifier", identifier, obj=calculation_object, inside_list=inside_list, index=index)
|
self.set_calculation(
|
||||||
|
"identifier",
|
||||||
|
identifier,
|
||||||
|
obj=calculation_object,
|
||||||
|
inside_list=inside_list,
|
||||||
|
index=index,
|
||||||
|
)
|
||||||
|
|
||||||
def set_params_calculation(self, calculation_object: dict, attribute: str) -> None:
|
def set_params_calculation(self, calculation_object: dict, attribute: str) -> None:
|
||||||
if "params" not in calculation_object:
|
if "params" not in calculation_object:
|
||||||
|
|
@ -686,12 +770,18 @@ class Collect(CollectType, CollectFamily, CollectVariable):
|
||||||
val["type"] = list(param_typ)[0]
|
val["type"] = list(param_typ)[0]
|
||||||
|
|
||||||
def is_redefine(self):
|
def is_redefine(self):
|
||||||
if self.path in self.objectspace.paths and self.option_type == "family" and not self.parameters:
|
if (
|
||||||
|
self.path in self.objectspace.paths
|
||||||
|
and self.option_type == "family"
|
||||||
|
and not self.parameters
|
||||||
|
):
|
||||||
# allow loading family with no attribute loaded
|
# allow loading family with no attribute loaded
|
||||||
return True
|
return True
|
||||||
if self.types:
|
if self.types:
|
||||||
return True
|
return True
|
||||||
return self.parameters.pop("redefine", False) or (self.types and list(self.parameters) in [[], ["default"]])
|
return self.parameters.pop("redefine", False) or (
|
||||||
|
self.types and list(self.parameters) in [[], ["default"]]
|
||||||
|
)
|
||||||
|
|
||||||
def is_exists(self):
|
def is_exists(self):
|
||||||
if self.version == "1.0" and self.option_type == "family":
|
if self.version == "1.0" and self.option_type == "family":
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,10 @@ class ParserVariable:
|
||||||
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") and rougailconfig.config.option('define_default_params').value.get():
|
if (
|
||||||
|
hasattr(rougailconfig, "config")
|
||||||
|
and rougailconfig.config.option("define_default_params").value.get()
|
||||||
|
):
|
||||||
for sub_od in rougailconfig.config.option("default_params"):
|
for sub_od in rougailconfig.config.option("default_params"):
|
||||||
for option in sub_od:
|
for option in sub_od:
|
||||||
if option.owner.isdefault():
|
if option.owner.isdefault():
|
||||||
|
|
@ -219,7 +222,9 @@ class ParserVariable:
|
||||||
)
|
)
|
||||||
if "Family" in module.__all__:
|
if "Family" in module.__all__:
|
||||||
self.family = type(
|
self.family = type(
|
||||||
self.family.__name__ + "_" + structural, (self.family, module.Family), {}
|
self.family.__name__ + "_" + structural,
|
||||||
|
(self.family, module.Family),
|
||||||
|
{},
|
||||||
)
|
)
|
||||||
if not self.walker and "Walker" in module.__all__:
|
if not self.walker and "Walker" in module.__all__:
|
||||||
self.walker = module.Walker
|
self.walker = module.Walker
|
||||||
|
|
@ -230,8 +235,19 @@ class ParserVariable:
|
||||||
variable_types.remove("choice")
|
variable_types.remove("choice")
|
||||||
variable_types.remove("regexp")
|
variable_types.remove("regexp")
|
||||||
variable_types.remove("symlink")
|
variable_types.remove("symlink")
|
||||||
self.variable_objects = [self.get_variable_object(obj, is_variable=True) for obj in [(self.variable, variable_types), SymLink, self.choices, self.regexp]]
|
self.variable_objects = [
|
||||||
self.family_objects = [self.get_variable_object(obj, is_variable=False) for obj in [self.dynamic, self.family]]
|
self.get_variable_object(obj, is_variable=True)
|
||||||
|
for obj in [
|
||||||
|
(self.variable, variable_types),
|
||||||
|
SymLink,
|
||||||
|
self.choices,
|
||||||
|
self.regexp,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
self.family_objects = [
|
||||||
|
self.get_variable_object(obj, is_variable=False)
|
||||||
|
for obj in [self.dynamic, self.family]
|
||||||
|
]
|
||||||
self.is_init = True
|
self.is_init = True
|
||||||
|
|
||||||
def get_variable_object(self, obj, *, is_variable: bool) -> dict:
|
def get_variable_object(self, obj, *, is_variable: bool) -> dict:
|
||||||
|
|
@ -241,11 +257,12 @@ class ParserVariable:
|
||||||
else:
|
else:
|
||||||
hint = get_type_hints(obj)
|
hint = get_type_hints(obj)
|
||||||
types = self.get_types(hint)
|
types = self.get_types(hint)
|
||||||
return {"object": obj,
|
return {
|
||||||
"types": types,
|
"object": obj,
|
||||||
"attrs": self.get_option_attrs(hint),
|
"types": types,
|
||||||
"attributes_types": self.get_attributes_types(hint, variable=is_variable),
|
"attrs": self.get_option_attrs(hint),
|
||||||
}
|
"attributes_types": self.get_attributes_types(hint, variable=is_variable),
|
||||||
|
}
|
||||||
|
|
||||||
def get_types(self, hint):
|
def get_types(self, hint):
|
||||||
return hint["type"].__args__
|
return hint["type"].__args__
|
||||||
|
|
@ -298,12 +315,13 @@ class ParserVariable:
|
||||||
path = option.path
|
path = option.path
|
||||||
redefine = option.redefine
|
redefine = option.redefine
|
||||||
exists = option.exists
|
exists = option.exists
|
||||||
# if not redefine and not exists and option.user_type in self.custom_family_types:
|
# if not redefine and not exists and option.user_type in self.custom_family_types:
|
||||||
types = option.types
|
types = option.types
|
||||||
if types:
|
if types:
|
||||||
self.add_family(types,
|
self.add_family(
|
||||||
custom_type=True,
|
types,
|
||||||
)
|
custom_type=True,
|
||||||
|
)
|
||||||
if path not in self.paths:
|
if path not in self.paths:
|
||||||
if not self.load_unexist_redefine and exists is None and redefine:
|
if not self.load_unexist_redefine and exists is None and redefine:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
|
|
@ -319,9 +337,7 @@ class ParserVariable:
|
||||||
else:
|
else:
|
||||||
if exists in [None, True] and not redefine:
|
if exists in [None, True] and not redefine:
|
||||||
msg = _('family "{0}" define multiple time').format(path)
|
msg = _('family "{0}" define multiple time').format(path)
|
||||||
raise DictConsistencyError(
|
raise DictConsistencyError(msg, 32, option.sources)
|
||||||
msg, 32, option.sources
|
|
||||||
)
|
|
||||||
if self.load_unexist_redefine or exists in [None, True]:
|
if self.load_unexist_redefine or exists in [None, True]:
|
||||||
objects = option.parameters.copy()
|
objects = option.parameters.copy()
|
||||||
objects["xmlfiles"] = option.sources
|
objects["xmlfiles"] = option.sources
|
||||||
|
|
@ -329,7 +345,7 @@ class ParserVariable:
|
||||||
option,
|
option,
|
||||||
self.paths[path].model_copy(update=objects),
|
self.paths[path].model_copy(update=objects),
|
||||||
force=True,
|
force=True,
|
||||||
)
|
)
|
||||||
force_not_first = types == None
|
force_not_first = types == None
|
||||||
children = option.children
|
children = option.children
|
||||||
for idx, key in enumerate(self.list_children(option, types)):
|
for idx, key in enumerate(self.list_children(option, types)):
|
||||||
|
|
@ -394,7 +410,7 @@ class ParserVariable:
|
||||||
self,
|
self,
|
||||||
option: Collect,
|
option: Collect,
|
||||||
*,
|
*,
|
||||||
custom_type: bool=False,
|
custom_type: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Add a new family"""
|
"""Add a new family"""
|
||||||
path = option.path
|
path = option.path
|
||||||
|
|
@ -415,12 +431,15 @@ class ParserVariable:
|
||||||
try:
|
try:
|
||||||
self.paths.add(
|
self.paths.add(
|
||||||
option,
|
option,
|
||||||
family_obj(name=option.name,
|
family_obj(
|
||||||
**data,
|
name=option.name,
|
||||||
),
|
**data,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
raise Exception(f'invalid family "{path}" in "{display_list(option.sources)}": {err}') from err
|
raise Exception(
|
||||||
|
f'invalid family "{path}" in "{display_list(option.sources)}": {err}'
|
||||||
|
) from err
|
||||||
self.set_name(
|
self.set_name(
|
||||||
self.paths[path],
|
self.paths[path],
|
||||||
"optiondescription_",
|
"optiondescription_",
|
||||||
|
|
@ -448,10 +467,11 @@ class ParserVariable:
|
||||||
path = option.path
|
path = option.path
|
||||||
if option.types:
|
if option.types:
|
||||||
redefine = True
|
redefine = True
|
||||||
self.add_variable(option.types,
|
self.add_variable(
|
||||||
first_variable=first_variable,
|
option.types,
|
||||||
custom_type=True,
|
first_variable=first_variable,
|
||||||
)
|
custom_type=True,
|
||||||
|
)
|
||||||
if path not in self.paths:
|
if path not in self.paths:
|
||||||
if not self.load_unexist_redefine and exists is True:
|
if not self.load_unexist_redefine and exists is True:
|
||||||
# this variable must exist
|
# this variable must exist
|
||||||
|
|
@ -461,19 +481,18 @@ class ParserVariable:
|
||||||
if not self.load_unexist_redefine and redefine:
|
if not self.load_unexist_redefine and redefine:
|
||||||
msg = f'cannot redefine the inexisting variable "{path}"'
|
msg = f'cannot redefine the inexisting variable "{path}"'
|
||||||
raise DictConsistencyError(msg, 46, option.sources)
|
raise DictConsistencyError(msg, 46, option.sources)
|
||||||
self.add_variable(option,
|
self.add_variable(
|
||||||
first_variable,
|
option,
|
||||||
custom_type,
|
first_variable,
|
||||||
)
|
custom_type,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if not self.load_unexist_redefine:
|
if not self.load_unexist_redefine:
|
||||||
if exists is False:
|
if exists is False:
|
||||||
return
|
return
|
||||||
if not redefine:
|
if not redefine:
|
||||||
msg = _('variable "{0}" define multiple time').format(path)
|
msg = _('variable "{0}" define multiple time').format(path)
|
||||||
raise DictConsistencyError(
|
raise DictConsistencyError(msg, 45, option.sources)
|
||||||
msg, 45, option.sources
|
|
||||||
)
|
|
||||||
objects = option.parameters.copy()
|
objects = option.parameters.copy()
|
||||||
objects["xmlfiles"] = option.sources
|
objects["xmlfiles"] = option.sources
|
||||||
self.paths.add(
|
self.paths.add(
|
||||||
|
|
@ -499,9 +518,10 @@ class ParserVariable:
|
||||||
data["path"] = path
|
data["path"] = path
|
||||||
data["version"] = option.version
|
data["version"] = option.version
|
||||||
try:
|
try:
|
||||||
variable_obj = option.object["object"](name=option.name,
|
variable_obj = option.object["object"](
|
||||||
**data,
|
name=option.name,
|
||||||
)
|
**data,
|
||||||
|
)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f'invalid variable "{path}" in "{display_list(option.sources)}": {err}'
|
f'invalid variable "{path}" in "{display_list(option.sources)}": {err}'
|
||||||
|
|
@ -572,12 +592,13 @@ class ParserVariable:
|
||||||
class RougailConvert(ParserVariable):
|
class RougailConvert(ParserVariable):
|
||||||
"""Main Rougail conversion"""
|
"""Main Rougail conversion"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(
|
||||||
rougailconfig,
|
self,
|
||||||
*,
|
rougailconfig,
|
||||||
custom_variable_types: dict={},
|
*,
|
||||||
custom_family_types: dict={},
|
custom_variable_types: dict = {},
|
||||||
) -> None:
|
custom_family_types: dict = {},
|
||||||
|
) -> None:
|
||||||
self.annotator = False
|
self.annotator = False
|
||||||
self.has_namespace = False
|
self.has_namespace = False
|
||||||
self.custom_variable_types = custom_variable_types
|
self.custom_variable_types = custom_variable_types
|
||||||
|
|
@ -588,14 +609,16 @@ class RougailConvert(ParserVariable):
|
||||||
def get_attributes_types(
|
def get_attributes_types(
|
||||||
self,
|
self,
|
||||||
hint: dict,
|
hint: dict,
|
||||||
variable: bool=False,
|
variable: bool = False,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""attribute is calculated if typing is like: Union[Calculation, xxx]"""
|
"""attribute is calculated if typing is like: Union[Calculation, xxx]"""
|
||||||
lists = {"strings": [],
|
lists = {
|
||||||
"booleans": [],
|
"strings": [],
|
||||||
"integers": [],
|
"booleans": [],
|
||||||
"floats": [],
|
"integers": [],
|
||||||
"calculation": []}
|
"floats": [],
|
||||||
|
"calculation": [],
|
||||||
|
}
|
||||||
if variable:
|
if variable:
|
||||||
lists["calculation"].append("identifier")
|
lists["calculation"].append("identifier")
|
||||||
calculation = ["identifier"]
|
calculation = ["identifier"]
|
||||||
|
|
@ -647,18 +670,21 @@ class RougailConvert(ParserVariable):
|
||||||
booleans.append(key)
|
booleans.append(key)
|
||||||
elif "Literal" in value.__class__.__name__:
|
elif "Literal" in value.__class__.__name__:
|
||||||
literals[key] = value.__args__
|
literals[key] = value.__args__
|
||||||
return {"strings": strings,
|
return {
|
||||||
"integers": integers,
|
"strings": strings,
|
||||||
"booleans": booleans,
|
"integers": integers,
|
||||||
"floats": floats,
|
"booleans": booleans,
|
||||||
"literals": literals,
|
"floats": floats,
|
||||||
"calculation": calculation,
|
"literals": literals,
|
||||||
"lists": lists,
|
"calculation": calculation,
|
||||||
"params": params,
|
"lists": lists,
|
||||||
}
|
"params": params,
|
||||||
|
}
|
||||||
|
|
||||||
def create_namespace(
|
def create_namespace(
|
||||||
self, namespace_description: str, isolated_namespace: bool=True,
|
self,
|
||||||
|
namespace_description: str,
|
||||||
|
isolated_namespace: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
namespace_path = normalize_family(namespace_description)
|
namespace_path = normalize_family(namespace_description)
|
||||||
self.has_namespace = True
|
self.has_namespace = True
|
||||||
|
|
@ -687,9 +713,7 @@ class RougailConvert(ParserVariable):
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
self.parse_family(
|
self.parse_family(option)
|
||||||
option
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_comment(
|
def get_comment(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,11 @@ from ..utils import (
|
||||||
PROPERTY_ATTRIBUTE,
|
PROPERTY_ATTRIBUTE,
|
||||||
)
|
)
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..error import DictConsistencyError, VariableCalculationDependencyError, RougailWarning
|
from ..error import (
|
||||||
|
DictConsistencyError,
|
||||||
|
VariableCalculationDependencyError,
|
||||||
|
RougailWarning,
|
||||||
|
)
|
||||||
from ..tiramisu import CONVERT_OPTION, RENAME_TYPE, display_xmlfiles, convert_boolean
|
from ..tiramisu import CONVERT_OPTION, RENAME_TYPE, display_xmlfiles, convert_boolean
|
||||||
|
|
||||||
BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None]
|
BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None]
|
||||||
|
|
@ -60,7 +64,7 @@ def get_convert_option_types():
|
||||||
if key.startswith("_"):
|
if key.startswith("_"):
|
||||||
continue
|
continue
|
||||||
if "params" in datas and key in datas["params"]:
|
if "params" in datas and key in datas["params"]:
|
||||||
multi = datas["params"][key].get('multi', False)
|
multi = datas["params"][key].get("multi", False)
|
||||||
description = datas["params"][key]["description"]
|
description = datas["params"][key]["description"]
|
||||||
choices = datas["params"][key].get("choices")
|
choices = datas["params"][key].get("choices")
|
||||||
else:
|
else:
|
||||||
|
|
@ -111,7 +115,7 @@ class VariableParam(Param):
|
||||||
variable: StrictStr
|
variable: StrictStr
|
||||||
propertyerror: bool = True
|
propertyerror: bool = True
|
||||||
whole: bool = False
|
whole: bool = False
|
||||||
# dynamic: bool = True
|
# dynamic: bool = True
|
||||||
optional: bool = False
|
optional: bool = False
|
||||||
|
|
||||||
def to_param(
|
def to_param(
|
||||||
|
|
@ -324,9 +328,16 @@ class JinjaCalculation(Calculation):
|
||||||
variable = objectspace.paths[path]
|
variable = objectspace.paths[path]
|
||||||
objectspace.jinja[jinja_path] = self.jinja
|
objectspace.jinja[jinja_path] = self.jinja
|
||||||
if return_type in RENAME_TYPE:
|
if return_type in RENAME_TYPE:
|
||||||
warning = _('the variable "{0}" has a depreciated return_type "{1}", please use "{2}" instead in {3}')
|
warning = _(
|
||||||
|
'the variable "{0}" has a depreciated return_type "{1}", please use "{2}" instead in {3}'
|
||||||
|
)
|
||||||
warn(
|
warn(
|
||||||
warning.format(path, return_type, RENAME_TYPE[return_type], display_xmlfiles(self.xmlfiles)),
|
warning.format(
|
||||||
|
path,
|
||||||
|
return_type,
|
||||||
|
RENAME_TYPE[return_type],
|
||||||
|
display_xmlfiles(self.xmlfiles),
|
||||||
|
),
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
|
|
@ -416,19 +427,26 @@ class JinjaCalculation(Calculation):
|
||||||
'variable "{0}" has a calculating "{1}" with an invalid return_type, should be boolean or string, not "{2}"'
|
'variable "{0}" has a calculating "{1}" with an invalid return_type, should be boolean or string, not "{2}"'
|
||||||
).format(path, self.attribute_name, return_type)
|
).format(path, self.attribute_name, return_type)
|
||||||
raise DictConsistencyError(msg, 81, self.xmlfiles)
|
raise DictConsistencyError(msg, 81, self.xmlfiles)
|
||||||
if return_type == 'boolean':
|
if return_type == "boolean":
|
||||||
description = self.description
|
description = self.description
|
||||||
if description is None:
|
if description is None:
|
||||||
if self.ori_path is not None:
|
if self.ori_path is not None:
|
||||||
opath = self.ori_path
|
opath = self.ori_path
|
||||||
else:
|
else:
|
||||||
opath = path
|
opath = path
|
||||||
warning = _('the variable "{0}" has a return_type "{1}", for attribute "{2}" but has not description in {3}')
|
warning = _(
|
||||||
|
'the variable "{0}" has a return_type "{1}", for attribute "{2}" but has not description in {3}'
|
||||||
|
)
|
||||||
warn(
|
warn(
|
||||||
warning.format(opath, return_type, self.attribute_name, display_xmlfiles(self.xmlfiles)),
|
warning.format(
|
||||||
|
opath,
|
||||||
|
return_type,
|
||||||
|
self.attribute_name,
|
||||||
|
display_xmlfiles(self.xmlfiles),
|
||||||
|
),
|
||||||
RougailWarning,
|
RougailWarning,
|
||||||
)
|
)
|
||||||
self.description = _('value is invalid')
|
self.description = _("value is invalid")
|
||||||
else:
|
else:
|
||||||
description = None
|
description = None
|
||||||
return self._jinja_to_function(
|
return self._jinja_to_function(
|
||||||
|
|
@ -437,7 +455,7 @@ class JinjaCalculation(Calculation):
|
||||||
False,
|
False,
|
||||||
objectspace,
|
objectspace,
|
||||||
path,
|
path,
|
||||||
params={'description': description},
|
params={"description": description},
|
||||||
)
|
)
|
||||||
elif self.attribute_name in PROPERTY_ATTRIBUTE:
|
elif self.attribute_name in PROPERTY_ATTRIBUTE:
|
||||||
return_type = self.return_type
|
return_type = self.return_type
|
||||||
|
|
@ -491,7 +509,7 @@ class JinjaCalculation(Calculation):
|
||||||
|
|
||||||
class _VariableCalculation(Calculation):
|
class _VariableCalculation(Calculation):
|
||||||
variable: StrictStr
|
variable: StrictStr
|
||||||
propertyerror: bool = True,
|
propertyerror: bool = (True,)
|
||||||
allow_none: bool = False
|
allow_none: bool = False
|
||||||
optional: bool = False
|
optional: bool = False
|
||||||
# FIXME identifier is not available for Properties!
|
# FIXME identifier is not available for Properties!
|
||||||
|
|
@ -522,7 +540,9 @@ class _VariableCalculation(Calculation):
|
||||||
self.namespace,
|
self.namespace,
|
||||||
self.xmlfiles,
|
self.xmlfiles,
|
||||||
)
|
)
|
||||||
if variable and not isinstance(variable, objectspace.variable_objects[0]["object"]):
|
if variable and not isinstance(
|
||||||
|
variable, objectspace.variable_objects[0]["object"]
|
||||||
|
):
|
||||||
if isinstance(variable, objectspace.family):
|
if isinstance(variable, objectspace.family):
|
||||||
msg = _(
|
msg = _(
|
||||||
'a variable "{0}" is needs in attribute "{1}" for "{2}" but it\'s a family'
|
'a variable "{0}" is needs in attribute "{1}" for "{2}" but it\'s a family'
|
||||||
|
|
@ -549,7 +569,13 @@ class _VariableCalculation(Calculation):
|
||||||
if variable_in_calculation_identifier:
|
if variable_in_calculation_identifier:
|
||||||
msg = _(
|
msg = _(
|
||||||
'variable "{0}" has an attribute "{1}" with an identifier "{2}" but the path has also the identifier "{3}"'
|
'variable "{0}" has an attribute "{1}" with an identifier "{2}" but the path has also the identifier "{3}"'
|
||||||
).format(path, self.attribute_name, self.variable, self.identifier, variable_in_calculation_identifier)
|
).format(
|
||||||
|
path,
|
||||||
|
self.attribute_name,
|
||||||
|
self.variable,
|
||||||
|
self.identifier,
|
||||||
|
variable_in_calculation_identifier,
|
||||||
|
)
|
||||||
raise DictConsistencyError(msg, 89, self.xmlfiles)
|
raise DictConsistencyError(msg, 89, self.xmlfiles)
|
||||||
variable_in_calculation_identifier = self.identifier
|
variable_in_calculation_identifier = self.identifier
|
||||||
identifier_is_a_calculation = True
|
identifier_is_a_calculation = True
|
||||||
|
|
@ -578,7 +604,11 @@ class _VariableCalculation(Calculation):
|
||||||
if self.allow_none:
|
if self.allow_none:
|
||||||
params["allow_none"] = True
|
params["allow_none"] = True
|
||||||
self.check_multi(
|
self.check_multi(
|
||||||
objectspace, path, variable_in_calculation_path, variable_in_calculation, identifier_is_a_calculation,
|
objectspace,
|
||||||
|
path,
|
||||||
|
variable_in_calculation_path,
|
||||||
|
variable_in_calculation,
|
||||||
|
identifier_is_a_calculation,
|
||||||
)
|
)
|
||||||
if path in objectspace.followers:
|
if path in objectspace.followers:
|
||||||
multi = objectspace.multis[path] == "submulti"
|
multi = objectspace.multis[path] == "submulti"
|
||||||
|
|
@ -589,7 +619,12 @@ class _VariableCalculation(Calculation):
|
||||||
return params
|
return params
|
||||||
|
|
||||||
def check_multi(
|
def check_multi(
|
||||||
self, objectspace, path, variable_in_calculation_path, variable_in_calculation, identifier_is_a_calculation,
|
self,
|
||||||
|
objectspace,
|
||||||
|
path,
|
||||||
|
variable_in_calculation_path,
|
||||||
|
variable_in_calculation,
|
||||||
|
identifier_is_a_calculation,
|
||||||
):
|
):
|
||||||
local_variable = objectspace.paths[path]
|
local_variable = objectspace.paths[path]
|
||||||
local_variable_multi, variable_in_calculation_multi = (
|
local_variable_multi, variable_in_calculation_multi = (
|
||||||
|
|
@ -1075,8 +1110,8 @@ class Family(BaseModel):
|
||||||
|
|
||||||
class Dynamic(BaseModel):
|
class Dynamic(BaseModel):
|
||||||
type: Literal["dynamic"] = "dynamic"
|
type: Literal["dynamic"] = "dynamic"
|
||||||
# # None only for format 1.0
|
# # None only for format 1.0
|
||||||
# variable: StrictStr = None
|
# variable: StrictStr = None
|
||||||
dynamic: Union[List[Union[StrictStr, Calculation]], Calculation]
|
dynamic: Union[List[Union[StrictStr, Calculation]], Calculation]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ class TiramisuReflector:
|
||||||
continue
|
continue
|
||||||
self.text["header"].append(f"load_functions('{funcs_path}')")
|
self.text["header"].append(f"load_functions('{funcs_path}')")
|
||||||
if self.objectspace.export_with_import:
|
if self.objectspace.export_with_import:
|
||||||
# if self.objectspace.has_namespace:
|
# if self.objectspace.has_namespace:
|
||||||
self.text["header"].extend(
|
self.text["header"].extend(
|
||||||
[
|
[
|
||||||
"try:",
|
"try:",
|
||||||
|
|
@ -343,12 +343,16 @@ class Common:
|
||||||
ret = f"ParamSelfOption(whole={whole}"
|
ret = f"ParamSelfOption(whole={whole}"
|
||||||
if not dynamic:
|
if not dynamic:
|
||||||
ret += ", dynamic=False"
|
ret += ", dynamic=False"
|
||||||
return ret + ')'
|
return ret + ")"
|
||||||
if whole:
|
if whole:
|
||||||
msg = _('variable param "{0}" has whole attribute but it\'s not allowed for external variable')
|
msg = _(
|
||||||
|
'variable param "{0}" has whole attribute but it\'s not allowed for external variable'
|
||||||
|
)
|
||||||
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
||||||
if not dynamic:
|
if not dynamic:
|
||||||
msg = _('variable param "{0}" has dynamic attribute but it\'s not allowed for external variable')
|
msg = _(
|
||||||
|
'variable param "{0}" has dynamic attribute but it\'s not allowed for external variable'
|
||||||
|
)
|
||||||
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
||||||
option_name = self.tiramisu.reflector_objects[variable.path].get(
|
option_name = self.tiramisu.reflector_objects[variable.path].get(
|
||||||
self.calls, self.elt.path
|
self.calls, self.elt.path
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class DictConsistencyError(Exception):
|
||||||
|
|
||||||
class NotFoundError(Exception):
|
class NotFoundError(Exception):
|
||||||
"not found error"
|
"not found error"
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,9 @@ class Annotator(Walk):
|
||||||
return
|
return
|
||||||
alternative_name = variable.alternative_name
|
alternative_name = variable.alternative_name
|
||||||
variable_path = variable.path
|
variable_path = variable.path
|
||||||
self.objectspace.informations.add(variable_path, "alternative_name", alternative_name)
|
self.objectspace.informations.add(
|
||||||
|
variable_path, "alternative_name", alternative_name
|
||||||
|
)
|
||||||
all_letters = ""
|
all_letters = ""
|
||||||
for letter in alternative_name:
|
for letter in alternative_name:
|
||||||
all_letters += letter
|
all_letters += letter
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,15 @@ You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from ruamel.yaml import YAML
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
from ..tiramisu import normalize_family
|
from ..tiramisu import normalize_family
|
||||||
from ..convert.path import Paths
|
from ..convert.path import Paths
|
||||||
#from ..error import DictConsistencyError
|
|
||||||
#from ..i18n import _
|
# from ..error import DictConsistencyError
|
||||||
|
# from ..i18n import _
|
||||||
|
|
||||||
|
|
||||||
class Walker:
|
class Walker:
|
||||||
|
|
@ -85,9 +85,9 @@ class Walker:
|
||||||
return
|
return
|
||||||
path = self.convert.namespace
|
path = self.convert.namespace
|
||||||
if path:
|
if path:
|
||||||
name = f'yaml file for {path}'
|
name = f"yaml file for {path}"
|
||||||
else:
|
else:
|
||||||
name = 'yaml file'
|
name = "yaml file"
|
||||||
version = self.convert.validate_file_version(
|
version = self.convert.validate_file_version(
|
||||||
objects,
|
objects,
|
||||||
name,
|
name,
|
||||||
|
|
@ -101,4 +101,3 @@ class Walker:
|
||||||
|
|
||||||
|
|
||||||
__all__ = ("Walker",)
|
__all__ = ("Walker",)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,4 +66,3 @@ extra_namespaces:
|
||||||
|
|
||||||
|
|
||||||
__all__ = "get_rougail_config"
|
__all__ = "get_rougail_config"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,90 +87,139 @@ def convert_boolean(value: str) -> bool:
|
||||||
return None
|
return None
|
||||||
raise Exception(_('unknown boolean value "{0}"').format(value))
|
raise Exception(_('unknown boolean value "{0}"').format(value))
|
||||||
|
|
||||||
|
|
||||||
_ip_params = {
|
_ip_params = {
|
||||||
"cidr": {"description": _("IP must be in CIDR format")},
|
"cidr": {"description": _("IP must be in CIDR format")},
|
||||||
"private_only": {"description": _("private IP are allowed")},
|
"private_only": {"description": _("private IP are allowed")},
|
||||||
"allow_reserved": {"description": _("reserved IP are allowed")},
|
"allow_reserved": {"description": _("reserved IP are allowed")},
|
||||||
}
|
}
|
||||||
_network_params = {
|
_network_params = {
|
||||||
"cidr": {"description": _("network must be in CIDR format")},
|
"cidr": {"description": _("network must be in CIDR format")},
|
||||||
"private_only": {"description": _("private network are allowed")},
|
"private_only": {"description": _("private network are allowed")},
|
||||||
"allow_reserved": {"description": _("reserved network are allowed")},
|
"allow_reserved": {"description": _("reserved network are allowed")},
|
||||||
}
|
}
|
||||||
_port_params = {
|
_port_params = {
|
||||||
"allow_range": {"description": _("can be range of port")},
|
"allow_range": {"description": _("can be range of port")},
|
||||||
"allow_protocol": {"description": _("can have the protocol")},
|
"allow_protocol": {"description": _("can have the protocol")},
|
||||||
"allow_zero": {"description": _("port 0 is allowed")},
|
"allow_zero": {"description": _("port 0 is allowed")},
|
||||||
"allow_wellknown": {"description": _("well-known ports (1 to 1023) are allowed")},
|
"allow_wellknown": {"description": _("well-known ports (1 to 1023) are allowed")},
|
||||||
"allow_registred": {"description": _("registred ports (1024 to 49151) are allowed")},
|
"allow_registred": {
|
||||||
"allow_private": {"description": _("private ports (greater than 49152) are allowed")},
|
"description": _("registred ports (1024 to 49151) are allowed")
|
||||||
}
|
},
|
||||||
|
"allow_private": {
|
||||||
|
"description": _("private ports (greater than 49152) are allowed")
|
||||||
|
},
|
||||||
|
}
|
||||||
_domain_params = {
|
_domain_params = {
|
||||||
"type": {"description": _("type of domainname"), "choices": ('domainname', 'netbios', 'hostname'), 'doc': _("type {0}")},
|
"type": {
|
||||||
"allow_startswith_dot": {"description": _("the domain name can starts by a dot")},
|
"description": _("type of domainname"),
|
||||||
"allow_without_dot": {"description": _("the domain name can be a hostname")},
|
"choices": ("domainname", "netbios", "hostname"),
|
||||||
"allow_ip": {"description": _("the domain name can be an IP")},
|
"doc": _("type {0}"),
|
||||||
"allow_cidr_network": {"description": _("the domain name can be network in CIDR format")},
|
},
|
||||||
"test_existence": {"description": _("the domain name must exist")},
|
"allow_startswith_dot": {"description": _("the domain name can starts by a dot")},
|
||||||
}
|
"allow_without_dot": {"description": _("the domain name can be a hostname")},
|
||||||
|
"allow_ip": {"description": _("the domain name can be an IP")},
|
||||||
|
"allow_cidr_network": {
|
||||||
|
"description": _("the domain name can be network in CIDR format")
|
||||||
|
},
|
||||||
|
"test_existence": {"description": _("the domain name must exist")},
|
||||||
|
}
|
||||||
_web_params = _port_params | _domain_params
|
_web_params = _port_params | _domain_params
|
||||||
|
|
||||||
|
|
||||||
CONVERT_OPTION = {
|
CONVERT_OPTION = {
|
||||||
"string": dict(opttype="StrOption", example="example"),
|
"string": dict(opttype="StrOption", example="example"),
|
||||||
"number": dict(opttype="IntOption",
|
"number": dict(
|
||||||
func=int,
|
opttype="IntOption",
|
||||||
params={
|
func=int,
|
||||||
"min_number": {"description": _("the minimum value"), 'doc': _("the minimum value is {0}")},
|
params={
|
||||||
"max_number": {"description": _("the maximum value"), 'doc': _("the maximum value is {0}")},
|
"min_number": {
|
||||||
},
|
"description": _("the minimum value"),
|
||||||
example=42),
|
"doc": _("the minimum value is {0}"),
|
||||||
"integer": dict(opttype="IntOption",
|
},
|
||||||
params={
|
"max_number": {
|
||||||
"min_integer": {"description": _("the minimum value"), 'doc': _("the minimum value is {0}")},
|
"description": _("the maximum value"),
|
||||||
"max_integer": {"description": _("the maximum value"), 'doc': _("the maximum value is {0}")},
|
"doc": _("the maximum value is {0}"),
|
||||||
},
|
},
|
||||||
func=int,
|
},
|
||||||
example=42,
|
example=42,
|
||||||
),
|
),
|
||||||
|
"integer": dict(
|
||||||
|
opttype="IntOption",
|
||||||
|
params={
|
||||||
|
"min_integer": {
|
||||||
|
"description": _("the minimum value"),
|
||||||
|
"doc": _("the minimum value is {0}"),
|
||||||
|
},
|
||||||
|
"max_integer": {
|
||||||
|
"description": _("the maximum value"),
|
||||||
|
"doc": _("the maximum value is {0}"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func=int,
|
||||||
|
example=42,
|
||||||
|
),
|
||||||
"float": dict(opttype="FloatOption", func=float, example=1.42),
|
"float": dict(opttype="FloatOption", func=float, example=1.42),
|
||||||
"boolean": dict(opttype="BoolOption", func=convert_boolean, example=True),
|
"boolean": dict(opttype="BoolOption", func=convert_boolean, example=True),
|
||||||
"secret": dict(opttype="PasswordOption",
|
"secret": dict(
|
||||||
params={
|
opttype="PasswordOption",
|
||||||
"min_len": {"description": _("minimum characters length for the secret"), "doc": _("minimum length for the secret is {0} characters")},
|
params={
|
||||||
"max_len": {"description": _("maximum characters length for the secret"), "doc": _("maximum length for the secret is {0} characters")},
|
"min_len": {
|
||||||
"forbidden_char": {"description": _("forbidden characters"), "doc": _("forbidden characters: {0}")},
|
"description": _("minimum characters length for the secret"),
|
||||||
},
|
"doc": _("minimum length for the secret is {0} characters"),
|
||||||
example="secrets"),
|
},
|
||||||
|
"max_len": {
|
||||||
|
"description": _("maximum characters length for the secret"),
|
||||||
|
"doc": _("maximum length for the secret is {0} characters"),
|
||||||
|
},
|
||||||
|
"forbidden_char": {
|
||||||
|
"description": _("forbidden characters"),
|
||||||
|
"doc": _("forbidden characters: {0}"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example="secrets",
|
||||||
|
),
|
||||||
"mail": dict(opttype="EmailOption", example="user@example.net"),
|
"mail": dict(opttype="EmailOption", example="user@example.net"),
|
||||||
"unix_filename": dict(opttype="FilenameOption",
|
"unix_filename": dict(
|
||||||
msg="UNIX filename",
|
opttype="FilenameOption",
|
||||||
params={
|
msg="UNIX filename",
|
||||||
"allow_relative": {"description": _("this filename could be a relative path")},
|
params={
|
||||||
"test_existence": {"description": _("this file must exist")},
|
"allow_relative": {
|
||||||
"types": {"description": _("file type allowed"), "doc": _("file type allowed: {0}"), "choices": ("file", "directory"), "multi": True},
|
"description": _("this filename could be a relative path")
|
||||||
},
|
},
|
||||||
example="/tmp/myfile.txt"),
|
"test_existence": {"description": _("this file must exist")},
|
||||||
|
"types": {
|
||||||
|
"description": _("file type allowed"),
|
||||||
|
"doc": _("file type allowed: {0}"),
|
||||||
|
"choices": ("file", "directory"),
|
||||||
|
"multi": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example="/tmp/myfile.txt",
|
||||||
|
),
|
||||||
"date": dict(opttype="DateOption", example="2000-01-01"),
|
"date": dict(opttype="DateOption", example="2000-01-01"),
|
||||||
"unix_user": dict(opttype="UsernameOption", example="username",
|
"unix_user": dict(opttype="UsernameOption", example="username", msg="UNIX user"),
|
||||||
msg="UNIX user"
|
|
||||||
),
|
|
||||||
"ip": dict(
|
"ip": dict(
|
||||||
opttype="IPOption", initkwargs={"allow_reserved": True},
|
opttype="IPOption",
|
||||||
|
initkwargs={"allow_reserved": True},
|
||||||
msg="IP",
|
msg="IP",
|
||||||
params=_ip_params,
|
params=_ip_params,
|
||||||
example="1.1.1.1"
|
example="1.1.1.1",
|
||||||
|
),
|
||||||
|
"cidr": dict(
|
||||||
|
opttype="IPOption",
|
||||||
|
msg="CIDR",
|
||||||
|
initkwargs={"cidr": True},
|
||||||
|
params=_ip_params,
|
||||||
|
example="1.1.1.0/24",
|
||||||
),
|
),
|
||||||
"cidr": dict(opttype="IPOption", msg="CIDR", initkwargs={"cidr": True},
|
|
||||||
params=_ip_params,
|
|
||||||
example="1.1.1.0/24"),
|
|
||||||
"netmask": dict(opttype="NetmaskOption", example="255.255.255.0"),
|
"netmask": dict(opttype="NetmaskOption", example="255.255.255.0"),
|
||||||
"network": dict(opttype="NetworkOption",
|
"network": dict(opttype="NetworkOption", params=_network_params, example="1.1.1.0"),
|
||||||
params=_network_params,
|
|
||||||
example="1.1.1.0"),
|
|
||||||
"network_cidr": dict(
|
"network_cidr": dict(
|
||||||
opttype="NetworkOption", initkwargs={"cidr": True}, example="1.1.1.0/24",
|
opttype="NetworkOption",
|
||||||
params=_network_params,
|
initkwargs={"cidr": True},
|
||||||
|
example="1.1.1.0/24",
|
||||||
|
params=_network_params,
|
||||||
msg="network CIDR",
|
msg="network CIDR",
|
||||||
),
|
),
|
||||||
"broadcast": dict(opttype="BroadcastOption", example="1.1.1.255"),
|
"broadcast": dict(opttype="BroadcastOption", example="1.1.1.255"),
|
||||||
|
|
@ -200,9 +249,11 @@ CONVERT_OPTION = {
|
||||||
example="https://example.net",
|
example="https://example.net",
|
||||||
),
|
),
|
||||||
"port": dict(
|
"port": dict(
|
||||||
opttype="PortOption", initkwargs={"allow_private": True},
|
opttype="PortOption",
|
||||||
|
initkwargs={"allow_private": True},
|
||||||
params=_port_params,
|
params=_port_params,
|
||||||
example="111", func=str,
|
example="111",
|
||||||
|
func=str,
|
||||||
),
|
),
|
||||||
"mac": dict(opttype="MACOption", example="00:00:00:00:00"),
|
"mac": dict(opttype="MACOption", example="00:00:00:00:00"),
|
||||||
"unix_permissions": dict(
|
"unix_permissions": dict(
|
||||||
|
|
@ -218,9 +269,10 @@ CONVERT_OPTION = {
|
||||||
"symlink": dict(opttype="SymLinkOption"),
|
"symlink": dict(opttype="SymLinkOption"),
|
||||||
}
|
}
|
||||||
# only version 1.1
|
# only version 1.1
|
||||||
RENAME_TYPE = {"number": "integer",
|
RENAME_TYPE = {
|
||||||
"leadership": "sequence",
|
"number": "integer",
|
||||||
}
|
"leadership": "sequence",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_identifier_from_dynamic_family(true_name, name) -> str:
|
def get_identifier_from_dynamic_family(true_name, name) -> str:
|
||||||
|
|
@ -240,7 +292,9 @@ def raise_carry_out_calculation_error(subconfig, *args, **kwargs):
|
||||||
ymlfiles = subconfig.config_bag.context.get_values().get_information(
|
ymlfiles = subconfig.config_bag.context.get_values().get_information(
|
||||||
subconfig, "ymlfiles", []
|
subconfig, "ymlfiles", []
|
||||||
)
|
)
|
||||||
raise ConfigError(_("{0} in {1}").format(err, display_xmlfiles(ymlfiles)), subconfig=subconfig)
|
raise ConfigError(
|
||||||
|
_("{0} in {1}").format(err, display_xmlfiles(ymlfiles)), subconfig=subconfig
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error
|
errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error
|
||||||
|
|
@ -249,7 +303,7 @@ errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error
|
||||||
global func
|
global func
|
||||||
dict_env = {}
|
dict_env = {}
|
||||||
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
|
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
|
||||||
ENV.add_extension('jinja2.ext.do')
|
ENV.add_extension("jinja2.ext.do")
|
||||||
func = ENV.filters
|
func = ENV.filters
|
||||||
|
|
||||||
TMP_TEMPLATE = mkdtemp()
|
TMP_TEMPLATE = mkdtemp()
|
||||||
|
|
@ -258,6 +312,7 @@ ENV.compile_templates(TMP_TEMPLATE, zip=None)
|
||||||
|
|
||||||
atexit.register(rmtree, TMP_TEMPLATE)
|
atexit.register(rmtree, TMP_TEMPLATE)
|
||||||
|
|
||||||
|
|
||||||
class JinjaError:
|
class JinjaError:
|
||||||
__slot__ = ("_err",)
|
__slot__ = ("_err",)
|
||||||
|
|
||||||
|
|
@ -327,6 +382,7 @@ def tiramisu_display_name(
|
||||||
with_quote: bool = False,
|
with_quote: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Replace the Tiramisu display_name function to display path + description"""
|
"""Replace the Tiramisu display_name function to display path + description"""
|
||||||
|
|
||||||
def get_path():
|
def get_path():
|
||||||
if description_type in ["description", "name", "name_and_description"]:
|
if description_type in ["description", "name", "name_and_description"]:
|
||||||
path = kls.impl_getname()
|
path = kls.impl_getname()
|
||||||
|
|
@ -337,6 +393,7 @@ def tiramisu_display_name(
|
||||||
"{{ identifier }}", normalize_family(str(subconfig.identifiers[-1]))
|
"{{ identifier }}", normalize_family(str(subconfig.identifiers[-1]))
|
||||||
)
|
)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
config_bag = subconfig.config_bag
|
config_bag = subconfig.config_bag
|
||||||
context = config_bag.context
|
context = config_bag.context
|
||||||
values = context.get_values()
|
values = context.get_values()
|
||||||
|
|
@ -344,12 +401,23 @@ def tiramisu_display_name(
|
||||||
description_type = values.get_information(
|
description_type = values.get_information(
|
||||||
context_subconfig, "description_type", "name_and_description"
|
context_subconfig, "description_type", "name_and_description"
|
||||||
)
|
)
|
||||||
if description_type in ["description", "name_and_description", "path_and_description"]:
|
if description_type in [
|
||||||
|
"description",
|
||||||
|
"name_and_description",
|
||||||
|
"path_and_description",
|
||||||
|
]:
|
||||||
doc = values.get_information(subconfig, "doc", None)
|
doc = values.get_information(subconfig, "doc", None)
|
||||||
description = doc if doc and doc != kls.impl_getname() else ""
|
description = doc if doc and doc != kls.impl_getname() else ""
|
||||||
if "{{ identifier }}" in description and subconfig.identifiers:
|
if "{{ identifier }}" in description and subconfig.identifiers:
|
||||||
description = description.replace("{{ identifier }}", str(subconfig.identifiers[-1]))
|
description = description.replace(
|
||||||
if description_type in ["name", "path", "name_and_description", "path_and_description"]:
|
"{{ identifier }}", str(subconfig.identifiers[-1])
|
||||||
|
)
|
||||||
|
if description_type in [
|
||||||
|
"name",
|
||||||
|
"path",
|
||||||
|
"name_and_description",
|
||||||
|
"path_and_description",
|
||||||
|
]:
|
||||||
path = get_path()
|
path = get_path()
|
||||||
if description_type in ["name_and_description", "path_and_description"]:
|
if description_type in ["name_and_description", "path_and_description"]:
|
||||||
if description:
|
if description:
|
||||||
|
|
@ -414,15 +482,15 @@ def jinja_to_function(
|
||||||
for v in value:
|
for v in value:
|
||||||
if isinstance(v, PropertiesOptionError):
|
if isinstance(v, PropertiesOptionError):
|
||||||
v = JinjaError(v)
|
v = JinjaError(v)
|
||||||
# if v is None:
|
# if v is None:
|
||||||
# v = ''
|
# v = ''
|
||||||
val.append(v)
|
val.append(v)
|
||||||
value = val
|
value = val
|
||||||
else:
|
else:
|
||||||
if isinstance(value, PropertiesOptionError):
|
if isinstance(value, PropertiesOptionError):
|
||||||
value = JinjaError(value)
|
value = JinjaError(value)
|
||||||
# if value is None:
|
# if value is None:
|
||||||
# value = ''
|
# value = ''
|
||||||
if "." in key:
|
if "." in key:
|
||||||
c_kw = kw
|
c_kw = kw
|
||||||
path, var = key.rsplit(".", 1)
|
path, var = key.rsplit(".", 1)
|
||||||
|
|
@ -446,12 +514,14 @@ 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))
|
||||||
prefix = _('cannot calculate the variable "{0}"').format(__internal_variable)
|
prefix = _('cannot calculate the variable "{0}"').format(__internal_variable)
|
||||||
msg = _('the attribute "{0}" in {1} with the parameters "{2}" causes the error: {3}').format(
|
msg = _(
|
||||||
__internal_attribute,
|
'the attribute "{0}" in {1} with the parameters "{2}" causes the error: {3}'
|
||||||
display_xmlfiles(__internal_files),
|
).format(
|
||||||
kw_str,
|
__internal_attribute,
|
||||||
err,
|
display_xmlfiles(__internal_files),
|
||||||
)
|
kw_str,
|
||||||
|
err,
|
||||||
|
)
|
||||||
raise ConfigError(msg, prefix=prefix) from err
|
raise ConfigError(msg, prefix=prefix) from err
|
||||||
convert = CONVERT_OPTION[__internal_type].get("func", str)
|
convert = CONVERT_OPTION[__internal_type].get("func", str)
|
||||||
if __internal_multi:
|
if __internal_multi:
|
||||||
|
|
@ -468,10 +538,10 @@ def jinja_to_function(
|
||||||
msg = _('"{0}" is an invalid {1}').format(values, __internal_type)
|
msg = _('"{0}" is an invalid {1}').format(values, __internal_type)
|
||||||
if __internal_attribute != "default":
|
if __internal_attribute != "default":
|
||||||
msg = _('the attribute "{0}" in {1} causes the error: {2}').format(
|
msg = _('the attribute "{0}" in {1} causes the error: {2}').format(
|
||||||
__internal_attribute,
|
__internal_attribute,
|
||||||
display_xmlfiles(__internal_files),
|
display_xmlfiles(__internal_files),
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
raise ConfigError(msg, prefix=prefix) from err
|
raise ConfigError(msg, prefix=prefix) from err
|
||||||
values = values if values != "" and values != "None" else None
|
values = values if values != "" and values != "None" else None
|
||||||
if values is None and __default_value is not None:
|
if values is None and __default_value is not None:
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ details.
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .config import StaticRougailConvert
|
from .config import StaticRougailConvert
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .error import DictConsistencyError
|
from .error import DictConsistencyError
|
||||||
|
|
@ -27,17 +28,21 @@ class TypeRougailConvert(StaticRougailConvert):
|
||||||
secret_pattern: str,
|
secret_pattern: str,
|
||||||
default_structural_format_version: str,
|
default_structural_format_version: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(False, {"sort_structural_files_all": True,
|
super().__init__(
|
||||||
"main_namespace": None,
|
False,
|
||||||
"main_structural_directories": main_structural_directories,
|
{
|
||||||
})
|
"sort_structural_files_all": True,
|
||||||
|
"main_namespace": None,
|
||||||
|
"main_structural_directories": main_structural_directories,
|
||||||
|
},
|
||||||
|
)
|
||||||
self.default_structural_format_version = default_structural_format_version
|
self.default_structural_format_version = default_structural_format_version
|
||||||
self.secret_pattern = secret_pattern
|
self.secret_pattern = secret_pattern
|
||||||
self.loaded_custom_types = {}
|
self.loaded_custom_types = {}
|
||||||
|
|
||||||
def load_config(self) -> None:
|
def load_config(self) -> None:
|
||||||
super().load_config()
|
super().load_config()
|
||||||
# self.add_extra_options = self.add_extra_options
|
# self.add_extra_options = self.add_extra_options
|
||||||
self.sort_structural_files_all = False
|
self.sort_structural_files_all = False
|
||||||
self.structurals = ["directory"]
|
self.structurals = ["directory"]
|
||||||
|
|
||||||
|
|
@ -46,10 +51,11 @@ def rougail_type(rougailconfig):
|
||||||
types = rougailconfig["types"]
|
types = rougailconfig["types"]
|
||||||
if not types:
|
if not types:
|
||||||
return {"custom_variable_types": {}, "custom_family_types": {}}
|
return {"custom_variable_types": {}, "custom_family_types": {}}
|
||||||
convert = TypeRougailConvert(types,
|
convert = TypeRougailConvert(
|
||||||
rougailconfig["secret_manager.pattern"],
|
types,
|
||||||
rougailconfig["default_structural_format_version"],
|
rougailconfig["secret_manager.pattern"],
|
||||||
)
|
rougailconfig["default_structural_format_version"],
|
||||||
|
)
|
||||||
convert.init()
|
convert.init()
|
||||||
convert.parse_directories()
|
convert.parse_directories()
|
||||||
loaded_custom_types_keys = list(convert.loaded_custom_types)
|
loaded_custom_types_keys = list(convert.loaded_custom_types)
|
||||||
|
|
@ -68,10 +74,11 @@ def rougail_type(rougailconfig):
|
||||||
custom_variable_types = {}
|
custom_variable_types = {}
|
||||||
custom_family_types = {}
|
custom_family_types = {}
|
||||||
for typ, data in convert.loaded_custom_types.items():
|
for typ, data in convert.loaded_custom_types.items():
|
||||||
if data.option_type == 'variable':
|
if data.option_type == "variable":
|
||||||
custom_variable_types[typ] = data
|
custom_variable_types[typ] = data
|
||||||
else:
|
else:
|
||||||
custom_family_types[typ] = data
|
custom_family_types[typ] = data
|
||||||
return {"custom_variable_types": custom_variable_types,
|
return {
|
||||||
"custom_family_types": custom_family_types,
|
"custom_variable_types": custom_variable_types,
|
||||||
}
|
"custom_family_types": custom_family_types,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,12 @@ class UserData:
|
||||||
source = datas["source"]
|
source = datas["source"]
|
||||||
for name, data in datas.get("values", {}).items():
|
for name, data in datas.get("values", {}).items():
|
||||||
self.values.setdefault(name, []).append(
|
self.values.setdefault(name, []).append(
|
||||||
{
|
{
|
||||||
"source": source,
|
"source": source,
|
||||||
"values": data,
|
"values": data,
|
||||||
"options": options.copy(),
|
"options": options.copy(),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
self.errors.extend(datas.get("errors", []))
|
self.errors.extend(datas.get("errors", []))
|
||||||
self.warnings.extend(datas.get("warnings", []))
|
self.warnings.extend(datas.get("warnings", []))
|
||||||
|
|
||||||
|
|
@ -102,7 +103,7 @@ class UserData:
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg = str(err)
|
msg = str(err)
|
||||||
else:
|
else:
|
||||||
msg = _('{0}, it will be ignored').format(err)
|
msg = _("{0}, it will be ignored").format(err)
|
||||||
self.invalids.append({msg: err.subconfig})
|
self.invalids.append({msg: err.subconfig})
|
||||||
|
|
||||||
def _auto_configure_dynamics(self):
|
def _auto_configure_dynamics(self):
|
||||||
|
|
@ -211,7 +212,9 @@ class UserData:
|
||||||
if option.issubmulti():
|
if option.issubmulti():
|
||||||
for idx, val in enumerate(value):
|
for idx, val in enumerate(value):
|
||||||
if isinstance(val, list):
|
if isinstance(val, list):
|
||||||
value[idx] = [convert_value(option, v, needs_convert) for v in val]
|
value[idx] = [
|
||||||
|
convert_value(option, v, needs_convert) for v in val
|
||||||
|
]
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
value = [convert_value(option, val, needs_convert) for val in value]
|
value = [convert_value(option, val, needs_convert) for val in value]
|
||||||
if needs_convert:
|
if needs_convert:
|
||||||
|
|
@ -236,21 +239,26 @@ class UserData:
|
||||||
if option.type() == "password":
|
if option.type() == "password":
|
||||||
one_is_in_error = False
|
one_is_in_error = False
|
||||||
for values in self.values[values_path]:
|
for values in self.values[values_path]:
|
||||||
if values.get("options", {}).get("allow_secrets_variables", True) is False:
|
if (
|
||||||
|
values.get("options", {}).get(
|
||||||
|
"allow_secrets_variables", True
|
||||||
|
)
|
||||||
|
is False
|
||||||
|
):
|
||||||
one_is_in_error = True
|
one_is_in_error = True
|
||||||
self.errors.append({
|
self.errors.append(
|
||||||
_(
|
{
|
||||||
'the variable contains secrets and should not be defined in {0}'
|
_(
|
||||||
).format(values["source"]): option._subconfig}
|
"the variable contains secrets and should not be defined in {0}"
|
||||||
|
).format(values["source"]): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
if one_is_in_error:
|
if one_is_in_error:
|
||||||
self.values.pop(values_path)
|
self.values.pop(values_path)
|
||||||
continue
|
continue
|
||||||
values = self.values[values_path][-1]
|
values = self.values[values_path][-1]
|
||||||
options = values.get("options", {})
|
options = values.get("options", {})
|
||||||
value = self.convert_value(
|
value = self.convert_value(path, option, options, values["values"])
|
||||||
path, option, options, values["values"]
|
|
||||||
)
|
|
||||||
index = option.index()
|
index = option.index()
|
||||||
if index is not None:
|
if index is not None:
|
||||||
if isinstance(value, tuple):
|
if isinstance(value, tuple):
|
||||||
|
|
@ -278,8 +286,8 @@ class UserData:
|
||||||
value_is_set = True
|
value_is_set = True
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
pass
|
pass
|
||||||
# if path != option.path():
|
# if path != option.path():
|
||||||
# self.values[option.path()] = self.values.pop(values_path)
|
# self.values[option.path()] = self.values.pop(values_path)
|
||||||
else:
|
else:
|
||||||
# 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:
|
||||||
|
|
@ -326,34 +334,51 @@ class UserData:
|
||||||
if value:
|
if value:
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg = _(
|
msg = _(
|
||||||
'it\'s a family so we cannot set the value {0}, it has been loading from {1}'
|
"it's a family so we cannot set the value {0}, it has been loading from {1}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _(
|
||||||
'it\'s a family so we cannot set the value {0}, it will be ignored when loading from {1}'
|
"it's a family so we cannot set the value {0}, it will be ignored when loading from {1}"
|
||||||
)
|
)
|
||||||
self.invalids.append({msg.format(
|
self.invalids.append(
|
||||||
self._display_value(option, value),
|
{
|
||||||
options["source"],
|
msg.format(
|
||||||
): option._subconfig}
|
self._display_value(option, value),
|
||||||
|
options["source"],
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
if option.issymlinkoption():
|
if option.issymlinkoption():
|
||||||
err = _('it\'s a symlink option so we cannot set the value {0}').format(self._display_value(option, value))
|
err = _(
|
||||||
|
"it's a symlink option so we cannot set the value {0}"
|
||||||
|
).format(self._display_value(option, value))
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg = _('{0}, it has been loading from {1}').format(err, options["source"])
|
msg = _("{0}, it has been loading from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg = _('{0}, it will be ignored when loading from {1}').format(err, options["source"])
|
msg = _("{0}, it will be ignored when loading from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
)
|
||||||
self.unknowns.append({msg: option._subconfig})
|
self.unknowns.append({msg: option._subconfig})
|
||||||
continue
|
continue
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
self.invalids.append({
|
self.invalids.append(
|
||||||
_("{0}, it has been loaded from {1}").format(err, options["source"]): option._subconfig}
|
{
|
||||||
|
_("{0}, it has been loaded from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
self.unknowns.append({
|
self.unknowns.append(
|
||||||
_("{0}, it has been loaded from {1}").format(err, options["source"]): option._subconfig}
|
{
|
||||||
|
_("{0}, it has been loaded from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
@ -364,20 +389,16 @@ class UserData:
|
||||||
subconfig = None
|
subconfig = None
|
||||||
child_name = err_path
|
child_name = err_path
|
||||||
else:
|
else:
|
||||||
parent_path, child_name = err_path.rsplit('.', 1)
|
parent_path, child_name = err_path.rsplit(".", 1)
|
||||||
subconfig = self.config.option(parent_path)
|
subconfig = self.config.option(parent_path)
|
||||||
subconfig._set_subconfig()
|
subconfig._set_subconfig()
|
||||||
err_msg = _(
|
err_msg = _(
|
||||||
'variable or family "{0}" does not exist so cannot load "{1}"'
|
'variable or family "{0}" does not exist so cannot load "{1}"'
|
||||||
).format(child_name, path)
|
).format(child_name, path)
|
||||||
if self.unknown_user_data_error:
|
if self.unknown_user_data_error:
|
||||||
msg = _(
|
msg = _("{0}, it has been loading from {1}")
|
||||||
'{0}, it has been loading from {1}'
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _("{0}, it will be ignored when loading from {1}")
|
||||||
'{0}, it will be ignored when loading from {1}'
|
|
||||||
)
|
|
||||||
msg = msg.format(err_msg, options["source"])
|
msg = msg.format(err_msg, options["source"])
|
||||||
if subconfig is not None:
|
if subconfig is not None:
|
||||||
msg = {msg: subconfig._subconfig}
|
msg = {msg: subconfig._subconfig}
|
||||||
|
|
@ -385,13 +406,19 @@ class UserData:
|
||||||
elif err.code == "option-dynamic":
|
elif err.code == "option-dynamic":
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg = _(
|
msg = _(
|
||||||
'"{0}" is the name of a dynamic family, it has been loading from {1}'
|
'"{0}" is the name of a dynamic family, it has been loading from {1}'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _(
|
||||||
'"{0}" is the name of a dynamic family, it will be ignored when loading from {1}'
|
'"{0}" is the name of a dynamic family, it will be ignored when loading from {1}'
|
||||||
)
|
)
|
||||||
self.invalids.append({msg.format(option.description(with_quote=True), options["source"]): option._subconfig})
|
self.invalids.append(
|
||||||
|
{
|
||||||
|
msg.format(
|
||||||
|
option.description(with_quote=True), options["source"]
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.invalids.append(
|
self.invalids.append(
|
||||||
_("{0} loaded from {1}").format(err, options["source"])
|
_("{0} loaded from {1}").format(err, options["source"])
|
||||||
|
|
@ -430,7 +457,9 @@ class UserData:
|
||||||
[_(prop) for prop in err.proptype], add_quote=False
|
[_(prop) for prop in err.proptype], add_quote=False
|
||||||
)
|
)
|
||||||
err_path = err.subconfig.path
|
err_path = err.subconfig.path
|
||||||
err_description = err.subconfig.option.impl_get_display_name(err.subconfig, with_quote=True)
|
err_description = err.subconfig.option.impl_get_display_name(
|
||||||
|
err.subconfig, with_quote=True
|
||||||
|
)
|
||||||
display_name = option.description(with_quote=True)
|
display_name = option.description(with_quote=True)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
if path == err_path:
|
if path == err_path:
|
||||||
|
|
@ -442,13 +471,15 @@ class UserData:
|
||||||
msg = _(
|
msg = _(
|
||||||
'variable {0} at index "{1}" is {2}, it will be ignored when loading from {3}'
|
'variable {0} at index "{1}" is {2}, it will be ignored when loading from {3}'
|
||||||
)
|
)
|
||||||
self.unknowns.append({
|
self.unknowns.append(
|
||||||
msg.format(
|
{
|
||||||
display_name,
|
msg.format(
|
||||||
index,
|
display_name,
|
||||||
properties,
|
index,
|
||||||
options["source"],
|
properties,
|
||||||
): option._subconfig}
|
options["source"],
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if self.unknown_user_data_error:
|
if self.unknown_user_data_error:
|
||||||
|
|
@ -459,14 +490,16 @@ class UserData:
|
||||||
msg = _(
|
msg = _(
|
||||||
'family {0} is {1}, {2} at index "{3}", it will be ignored when loading from {4}'
|
'family {0} is {1}, {2} at index "{3}", it will be ignored when loading from {4}'
|
||||||
)
|
)
|
||||||
self.unknowns.append({
|
self.unknowns.append(
|
||||||
msg.format(
|
{
|
||||||
err_description,
|
msg.format(
|
||||||
properties,
|
err_description,
|
||||||
display_name,
|
properties,
|
||||||
index,
|
display_name,
|
||||||
options["source"],
|
index,
|
||||||
): option._subconfig}
|
options["source"],
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if path == err_path:
|
if path == err_path:
|
||||||
|
|
@ -478,13 +511,17 @@ class UserData:
|
||||||
msg = _(
|
msg = _(
|
||||||
"variable has property {0}, it will be ignored when loading from {1}"
|
"variable has property {0}, it will be ignored when loading from {1}"
|
||||||
)
|
)
|
||||||
self.unknowns.append({
|
self.unknowns.append(
|
||||||
msg.format(
|
{
|
||||||
properties, options["source"]
|
msg.format(
|
||||||
): option._subconfig}
|
properties, options["source"]
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if not options.get("options", {}).get("secret_manager", False):
|
if not options.get("options", {}).get(
|
||||||
|
"secret_manager", False
|
||||||
|
):
|
||||||
if self.unknown_user_data_error:
|
if self.unknown_user_data_error:
|
||||||
msg = _(
|
msg = _(
|
||||||
"family {0} has property {1}, so cannot access to {2}, it has been loading from {3}"
|
"family {0} has property {1}, so cannot access to {2}, it has been loading from {3}"
|
||||||
|
|
@ -493,57 +530,59 @@ class UserData:
|
||||||
msg = _(
|
msg = _(
|
||||||
"family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}"
|
"family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}"
|
||||||
)
|
)
|
||||||
self.unknowns.append({
|
self.unknowns.append(
|
||||||
msg.format(
|
{
|
||||||
err_description,
|
msg.format(
|
||||||
properties,
|
err_description,
|
||||||
display_name,
|
properties,
|
||||||
options["source"],
|
display_name,
|
||||||
): option._subconfig}
|
options["source"],
|
||||||
|
): option._subconfig
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if self.unknown_user_data_error:
|
if self.unknown_user_data_error:
|
||||||
msg = _(
|
msg = _("{0}, it has been loading from {1}")
|
||||||
"{0}, it has been loading from {1}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _("{0}, it will be ignored when loading from {1}")
|
||||||
"{0}, it will be ignored when loading from {1}"
|
self.unknowns.append(
|
||||||
)
|
{msg.format(err, options["source"]): option._subconfig}
|
||||||
self.unknowns.append({
|
|
||||||
msg.format(err, options["source"]): option._subconfig}
|
|
||||||
)
|
)
|
||||||
except LeadershipError as err:
|
except LeadershipError as err:
|
||||||
if self.unknown_user_data_error:
|
if self.unknown_user_data_error:
|
||||||
msg = _(
|
msg = _("{0}, it has been loading from {1}")
|
||||||
"{0}, it has been loading from {1}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _("{0}, it will be ignored when loading from {1}")
|
||||||
"{0}, it will be ignored when loading from {1}"
|
self.unknowns.append(
|
||||||
)
|
{msg.format(err, options["source"]): option._subconfig}
|
||||||
self.unknowns.append({
|
|
||||||
msg.format(err, options["source"]): option._subconfig}
|
|
||||||
)
|
)
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
err.prefix = ""
|
err.prefix = ""
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg = _('{0}, it has been loading from {1}').format(err, options["source"])
|
msg = _("{0}, it has been loading from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg = _('{0}, it will be ignored when loading from {1}').format(err, options["source"])
|
msg = _("{0}, it will be ignored when loading from {1}").format(
|
||||||
|
err, options["source"]
|
||||||
|
)
|
||||||
self.invalids.append({msg: option._subconfig})
|
self.invalids.append({msg: option._subconfig})
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
err.prefix = ""
|
err.prefix = ""
|
||||||
type_ = option.type(translation=True)
|
type_ = option.type(translation=True)
|
||||||
msg = _('the value {0} is an invalid {1}, {2}').format(
|
msg = _("the value {0} is an invalid {1}, {2}").format(
|
||||||
self._display_value(option, value),
|
self._display_value(option, value),
|
||||||
type_,
|
type_,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
if self.invalid_user_data_error:
|
if self.invalid_user_data_error:
|
||||||
msg += _(', it has been loading from {0}').format(options["source"])
|
msg += _(", it has been loading from {0}").format(
|
||||||
|
options["source"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg += _(', it will be ignored when loading from {0}').format(options["source"])
|
msg += _(", it will be ignored when loading from {0}").format(
|
||||||
|
options["source"]
|
||||||
|
)
|
||||||
self.invalids.append({msg: option._subconfig})
|
self.invalids.append({msg: option._subconfig})
|
||||||
except AttributeOptionError as err:
|
except AttributeOptionError as err:
|
||||||
err.prefix = ""
|
err.prefix = ""
|
||||||
|
|
@ -557,10 +596,12 @@ class UserData:
|
||||||
if is_secret_manager and isinstance(value, tuple):
|
if is_secret_manager and isinstance(value, tuple):
|
||||||
# it's a function
|
# it's a function
|
||||||
params = tuple([ParamValue(val) for val in value[1:]])
|
params = tuple([ParamValue(val) for val in value[1:]])
|
||||||
option.information.set('secret_manager', True)
|
option.information.set("secret_manager", True)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
option = option.forcepermissive.index(index)
|
option = option.forcepermissive.index(index)
|
||||||
value = Calculation(value[0], Params(params, kwargs={"option": ParamValue(option)}))
|
value = Calculation(
|
||||||
|
value[0], Params(params, kwargs={"option": ParamValue(option)})
|
||||||
|
)
|
||||||
option = option.forcepermissive
|
option = option.forcepermissive
|
||||||
add_validation = True
|
add_validation = True
|
||||||
else:
|
else:
|
||||||
|
|
@ -586,9 +627,7 @@ class UserData:
|
||||||
key = f"loaded_from_{index}"
|
key = f"loaded_from_{index}"
|
||||||
else:
|
else:
|
||||||
key = "loaded_from"
|
key = "loaded_from"
|
||||||
value = _("loaded from {0}").format(
|
value = _("loaded from {0}").format(self.values[path][-1]["source"])
|
||||||
self.values[path][-1]["source"]
|
|
||||||
)
|
|
||||||
if options.get("secret_manager"):
|
if options.get("secret_manager"):
|
||||||
# FIXME (true_config ???)
|
# FIXME (true_config ???)
|
||||||
default = option.value.default()
|
default = option.value.default()
|
||||||
|
|
@ -658,12 +697,18 @@ def _populate_mandatory(option, errors: list) -> None:
|
||||||
if index is None:
|
if index is None:
|
||||||
msg = _("mandatory variable but has no value")
|
msg = _("mandatory variable but has no value")
|
||||||
else:
|
else:
|
||||||
msg = _('mandatory variable at index "{0}" but has no value').format(index)
|
msg = _('mandatory variable at index "{0}" but has no value').format(
|
||||||
|
index
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if index is None:
|
if index is None:
|
||||||
msg = _("mandatory variable but is inaccessible and has no value or has null in value")
|
msg = _(
|
||||||
|
"mandatory variable but is inaccessible and has no value or has null in value"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg = _('mandatory variable at index "{0}" but is inaccessible and has no value or has null in value').format(index)
|
msg = _(
|
||||||
|
'mandatory variable at index "{0}" but is inaccessible and has no value or has null in value'
|
||||||
|
).format(index)
|
||||||
else:
|
else:
|
||||||
proptype = option.value.mandatory(return_type=True)
|
proptype = option.value.mandatory(return_type=True)
|
||||||
if proptype == "empty":
|
if proptype == "empty":
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ def get_jinja_variable_to_param(
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
env = SandboxedEnvironment(loader=DictLoader({"tmpl": jinja_text}))
|
env = SandboxedEnvironment(loader=DictLoader({"tmpl": jinja_text}))
|
||||||
env.add_extension('jinja2.ext.do')
|
env.add_extension("jinja2.ext.do")
|
||||||
env.filters = functions
|
env.filters = functions
|
||||||
parsed_content = Parser(env, jinja_text, "", "").parse()
|
parsed_content = Parser(env, jinja_text, "", "").parse()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue