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