WIP: Expand the developer documentation #27

Draft
gremond wants to merge 226 commits from develop into developer_docs
12 changed files with 120 additions and 81 deletions
Showing only changes of commit f9c73783c5 - Show all commits

View file

@ -1,3 +1,9 @@
## 1.2.0a57 (2026-01-16)
### Fix
- add transition
## 1.2.0a56 (2026-01-15) ## 1.2.0a56 (2026-01-15)
### Fix ### Fix

View file

@ -1,6 +1,6 @@
[project] [project]
name = "rougail" name = "rougail"
version = "1.2.0a56" version = "1.2.0a57"
[tool.commitizen] [tool.commitizen]
name = "cz_conventional_commits" name = "cz_conventional_commits"

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail-base" name = "rougail-base"
version = "1.2.0a56" version = "1.2.0a57"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md" readme = "README.md"
description = "A consistency handling system that was initially designed in the configuration management" description = "A consistency handling system that was initially designed in the configuration management"

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail" name = "rougail"
version = "1.2.0a56" version = "1.2.0a57"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
description = "A consistency handling system that was initially designed in the configuration management" description = "A consistency handling system that was initially designed in the configuration management"
classifiers = [ classifiers = [
@ -18,7 +18,7 @@ classifiers = [
dependencies = [ dependencies = [
"ruamel.yaml ~= 0.18.6", "ruamel.yaml ~= 0.18.6",
"pydantic ~= 2.9.2", "pydantic ~= 2.9.2",
"rougail-base == 1.2.0a56", "rougail-base == 1.2.0a57",
] ]
[tool.flit.sdist] [tool.flit.sdist]

View file

@ -1 +1 @@
__version__ = "1.2.0a56" __version__ = "1.2.0a57"

View file

@ -124,8 +124,8 @@ class Annotator(Walk):
for calculation in frozen: for calculation in frozen:
calculation_copy = calculation.model_copy() calculation_copy = calculation.model_copy()
calculation_copy.attribute_name = "frozen" calculation_copy.attribute_name = "frozen"
calculation_copy.ori_path = calculation_copy.path # calculation_copy.ori_path = calculation_copy.path
calculation_copy.path = path # calculation_copy.path = path
value.append(calculation_copy) value.append(calculation_copy)
if len(value) == 1: if len(value) == 1:
value = value[0] value = value[0]

View file

@ -147,7 +147,7 @@ class Annotator(Walk): # pylint: disable=R0903
variable.type = "integer" variable.type = "integer"
elif isinstance(variable.default, VariableCalculation): elif isinstance(variable.default, VariableCalculation):
calculated_variable_path, calculated_variable, identifier = ( calculated_variable_path, calculated_variable, identifier = (
variable.default.get_variable(self.objectspace) variable.default.get_variable(self.objectspace, variable.path)
) )
if calculated_variable is not None: if calculated_variable is not None:
self._default_variable_copy_informations( self._default_variable_copy_informations(
@ -236,7 +236,7 @@ class Annotator(Walk): # pylint: disable=R0903
variable.default, VariableCalculation variable.default, VariableCalculation
): ):
calculated_variable_path, calculated_variable, identifier = ( calculated_variable_path, calculated_variable, identifier = (
variable.default.get_variable(self.objectspace) variable.default.get_variable(self.objectspace, variable.path)
) )
if calculated_variable is not None: if calculated_variable is not None:
if calculated_variable.multi is None: if calculated_variable.multi is None:

View file

@ -586,6 +586,7 @@ def _rougail_config(
tiram_obj = convert.save() tiram_obj = convert.save()
optiondescription = {} optiondescription = {}
print(tiram_obj)
exec(tiram_obj, {}, optiondescription) # pylint: disable=W0122 exec(tiram_obj, {}, optiondescription) # pylint: disable=W0122
return optiondescription["option_0"], extra_vars return optiondescription["option_0"], extra_vars

View file

@ -989,7 +989,7 @@ class ParserVariable:
typ = calculation_object.pop("type") typ = calculation_object.pop("type")
calculation_object["attribute_name"] = attribute calculation_object["attribute_name"] = attribute
calculation_object["path"] = path # calculation_object["path"] = path
calculation_object["inside_list"] = inside_list calculation_object["inside_list"] = inside_list
calculation_object["version"] = self.version calculation_object["version"] = self.version
calculation_object["namespace"] = self.namespace calculation_object["namespace"] = self.namespace

View file

@ -247,10 +247,10 @@ PARAM_TYPES = {
class Calculation(BaseModel): class Calculation(BaseModel):
path: str # path: str
inside_list: bool inside_list: bool
version: str version: str
ori_path: Optional[str] = None # ori_path: Optional[str] = None
default_values: Any = None default_values: Any = None
namespace: Optional[str] namespace: Optional[str]
warnings: Optional[bool] = None warnings: Optional[bool] = None
@ -258,7 +258,7 @@ class Calculation(BaseModel):
model_config = ConfigDict(extra="forbid") model_config = ConfigDict(extra="forbid")
def get_params(self, objectspace): def get_params(self, objectspace, path):
if self.warnings is not None and self.attribute_name != "validators": if self.warnings is not None and self.attribute_name != "validators":
msg = _( msg = _(
'"warnings" are only available with attribute "{self.attribute_name}" for variable "{self.ori_path}"' '"warnings" are only available with attribute "{self.attribute_name}" for variable "{self.ori_path}"'
@ -266,10 +266,10 @@ class Calculation(BaseModel):
raise DictConsistencyError(msg, 83, xmlfiles) raise DictConsistencyError(msg, 83, xmlfiles)
if not self.params: if not self.params:
return {} return {}
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
params = {} params = {}
for param_obj in self.params: for param_obj in self.params:
param = param_obj.to_param( param = param_obj.to_param(
@ -310,21 +310,22 @@ class JinjaCalculation(Calculation):
return_type, return_type,
multi, multi,
objectspace, objectspace,
path,
*, *,
add_help=False, add_help=False,
params: Optional[dict] = None, params: Optional[dict] = None,
): ):
variable = objectspace.paths[self.path] variable = objectspace.paths[path]
jinja_path = f"{self.attribute_name}_{self.path}" jinja_path = f"{self.attribute_name}_{path}"
idx = 0 idx = 0
while jinja_path in objectspace.jinja: while jinja_path in objectspace.jinja:
jinja_path = f"{self.attribute_name}_{self.path}_{idx}" jinja_path = f"{self.attribute_name}_{path}_{idx}"
idx += 1 idx += 1
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(self.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,
) )
@ -337,7 +338,7 @@ class JinjaCalculation(Calculation):
"__internal_multi": multi, "__internal_multi": multi,
"__internal_files": self.xmlfiles, "__internal_files": self.xmlfiles,
"__internal_attribute": self.attribute_name, "__internal_attribute": self.attribute_name,
"__internal_variable": self.path, "__internal_variable": path,
}, },
} }
if self.default_values: if self.default_values:
@ -345,13 +346,13 @@ class JinjaCalculation(Calculation):
if add_help: if add_help:
default["help"] = function + "_help" default["help"] = function + "_help"
if self.params: if self.params:
default["params"] |= self.get_params(objectspace) default["params"] |= self.get_params(objectspace, path)
if params: if params:
default["params"] |= params default["params"] |= params
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
if self.warnings: if self.warnings:
default["warnings_only"] = True default["warnings_only"] = True
for sub_variable, identifier, true_path in get_jinja_variable_to_param( for sub_variable, identifier, true_path in get_jinja_variable_to_param(
@ -385,33 +386,35 @@ class JinjaCalculation(Calculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
if self.attribute_name in ["default", "secret_manager"]: if self.attribute_name in ["default", "secret_manager"]:
if self.return_type: if self.return_type:
raise Exception("return_type not allowed!") raise Exception("return_type not allowed!")
variable = objectspace.paths[self.path] variable = objectspace.paths[path]
return_type = variable.type return_type = variable.type
if self.inside_list: if self.inside_list:
multi = False multi = False
elif self.path in objectspace.followers: elif path in objectspace.followers:
multi = objectspace.multis[self.path] == "submulti" multi = objectspace.multis[path] == "submulti"
else: else:
multi = self.path in objectspace.multis multi = path in objectspace.multis
return self._jinja_to_function( return self._jinja_to_function(
"jinja_to_function", "jinja_to_function",
return_type, return_type,
multi, multi,
objectspace, objectspace,
path,
) )
elif self.attribute_name == "validators": elif self.attribute_name == "validators":
return_type = self.return_type return_type = self.return_type
if return_type is None: if return_type is None:
return_type = "string" return_type = "string"
if return_type not in ["string", "boolean"]: if return_type not in ["string", "boolean"]:
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = path
else: # else:
path = self.ori_path # path = self.ori_path
msg = _( msg = _(
'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)
@ -421,7 +424,7 @@ class JinjaCalculation(Calculation):
if description is None: if description is None:
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(self.path, return_type, self.attribute_name, display_xmlfiles(self.xmlfiles)), warning.format(path, return_type, self.attribute_name, display_xmlfiles(self.xmlfiles)),
RougailWarning, RougailWarning,
) )
self.description = _('value is invalid') self.description = _('value is invalid')
@ -432,17 +435,18 @@ class JinjaCalculation(Calculation):
return_type, return_type,
False, False,
objectspace, objectspace,
params={'description': description} path,
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
if return_type is None: if return_type is None:
return_type = "string" return_type = "string"
if return_type not in ["string", "boolean"]: if return_type not in ["string", "boolean"]:
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = .path
else: # else:
path = self.ori_path # path = self.ori_path
msg = _( msg = _(
'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)
@ -453,6 +457,7 @@ class JinjaCalculation(Calculation):
return_type, return_type,
False, False,
objectspace, objectspace,
path,
add_help=True, add_help=True,
params={ params={
None: [self.attribute_name, description], None: [self.attribute_name, description],
@ -469,6 +474,7 @@ class JinjaCalculation(Calculation):
return_type, return_type,
not self.inside_list, not self.inside_list,
objectspace, objectspace,
path,
) )
elif self.attribute_name == "dynamic": elif self.attribute_name == "dynamic":
return_type = self.return_type return_type = self.return_type
@ -479,6 +485,7 @@ class JinjaCalculation(Calculation):
return_type, return_type,
True, True,
objectspace, objectspace,
path,
) )
raise Exception("hu?") raise Exception("hu?")
@ -492,11 +499,12 @@ class _VariableCalculation(Calculation):
def get_variable( def get_variable(
self, self,
objectspace, objectspace,
path,
) -> "Variable": ) -> "Variable":
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
if self.version != "1.0" and objectspace.paths.regexp_relative.search( if self.version != "1.0" and objectspace.paths.regexp_relative.search(
self.variable self.variable
): ):
@ -521,11 +529,11 @@ class _VariableCalculation(Calculation):
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'
).format(variable_full_path, self.attribute_name, self.path) ).format(variable_full_path, self.attribute_name, path)
raise DictConsistencyError(msg, 47, self.xmlfiles) raise DictConsistencyError(msg, 47, self.xmlfiles)
else: else:
msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format( msg = _('unknown object "{0}" in attribute "{1}" for "{2}"').format(
variable, self.attribute_name, self.path variable, self.attribute_name, path
) )
raise DictConsistencyError(msg, 48, self.xmlfiles) raise DictConsistencyError(msg, 48, self.xmlfiles)
return variable_full_path, variable, identifier return variable_full_path, variable, identifier
@ -533,6 +541,7 @@ class _VariableCalculation(Calculation):
def get_params( def get_params(
self, self,
objectspace, objectspace,
path,
variable_in_calculation_path: str, variable_in_calculation_path: str,
variable_in_calculation: "Variable", variable_in_calculation: "Variable",
variable_in_calculation_identifier: Optional[str], variable_in_calculation_identifier: Optional[str],
@ -540,10 +549,10 @@ class _VariableCalculation(Calculation):
): ):
if not variable_in_calculation: if not variable_in_calculation:
if not objectspace.force_optional: if not objectspace.force_optional:
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
msg = _( msg = _(
'variable "{0}" has an attribute "{1}" calculated with the unknown variable "{2}"' 'variable "{0}" has an attribute "{1}" calculated with the unknown variable "{2}"'
).format(path, self.attribute_name, self.variable) ).format(path, self.attribute_name, self.variable)
@ -567,23 +576,23 @@ 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, variable_in_calculation_path, variable_in_calculation objectspace, path, variable_in_calculation_path, variable_in_calculation
) )
if self.path in objectspace.followers: if path in objectspace.followers:
multi = objectspace.multis[self.path] == "submulti" multi = objectspace.multis[path] == "submulti"
else: else:
multi = self.path in objectspace.multis multi = path in objectspace.multis
if multi and not self.inside_list: if multi and not self.inside_list:
params["__internal_multi"] = True params["__internal_multi"] = True
return params return params
def check_multi( def check_multi(
self, objectspace, variable_in_calculation_path, variable_in_calculation self, objectspace, path, variable_in_calculation_path, variable_in_calculation
): ):
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
local_variable = objectspace.paths[path] local_variable = objectspace.paths[path]
local_variable_multi, variable_in_calculation_multi = ( local_variable_multi, variable_in_calculation_multi = (
calc_multi_for_type_variable( calc_multi_for_type_variable(
@ -696,14 +705,14 @@ class _VariableCalculation(Calculation):
) )
raise DictConsistencyError(msg, 18, self.xmlfiles) raise DictConsistencyError(msg, 18, self.xmlfiles)
def get_default_value_optional(self, objectspace, default): def get_default_value_optional(self, objectspace, path, default):
if self.attribute_name == "default": if self.attribute_name == "default":
if self.inside_list: if self.inside_list:
expected_multiple_value = False expected_multiple_value = False
elif self.path in objectspace.followers: elif path in objectspace.followers:
expected_multiple_value = objectspace.multis[self.path] == "submulti" expected_multiple_value = objectspace.multis[path] == "submulti"
else: else:
expected_multiple_value = self.path in objectspace.multis expected_multiple_value = path in objectspace.multis
elif self.attribute_name in PROPERTY_ATTRIBUTE: elif self.attribute_name in PROPERTY_ATTRIBUTE:
expected_multiple_value = False expected_multiple_value = False
else: else:
@ -718,7 +727,7 @@ class _VariableCalculation(Calculation):
msg = _( msg = _(
'the variable "{0}" is not waiting for a list as "{1}" but the attribute "default" is a list ("{2}")' 'the variable "{0}" is not waiting for a list as "{1}" but the attribute "default" is a list ("{2}")'
) )
msg = msg.format(self.path, self.attribute_name, default) msg = msg.format(path, self.attribute_name, default)
raise DictConsistencyError(msg, 77, self.xmlfiles) raise DictConsistencyError(msg, 77, self.xmlfiles)
return default return default
@ -731,6 +740,7 @@ class VariableCalculation(_VariableCalculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
if ( if (
self.attribute_name != "default" self.attribute_name != "default"
@ -745,7 +755,7 @@ class VariableCalculation(_VariableCalculation):
variable_in_calculation_path, variable_in_calculation_path,
variable_in_calculation, variable_in_calculation,
variable_in_calculation_identifier, variable_in_calculation_identifier,
) = self.get_variable(objectspace) ) = self.get_variable(objectspace, path)
if not variable_in_calculation and ( if not variable_in_calculation and (
self.optional or objectspace.force_optional self.optional or objectspace.force_optional
): ):
@ -755,16 +765,17 @@ class VariableCalculation(_VariableCalculation):
return self.default_values return self.default_values
raise VariableCalculationDependencyError() raise VariableCalculationDependencyError()
if variable_in_calculation and self.attribute_name == "default": if variable_in_calculation and self.attribute_name == "default":
local_variable = objectspace.paths[self.path] local_variable = objectspace.paths[path]
if CONVERT_OPTION.get(local_variable.type, {}).get( if CONVERT_OPTION.get(local_variable.type, {}).get(
"func", str "func", str
) != CONVERT_OPTION.get(variable_in_calculation.type, {}).get("func", str): ) != CONVERT_OPTION.get(variable_in_calculation.type, {}).get("func", str):
msg = _( msg = _(
'variable "{0}" has a default value calculated with "{1}" which has incompatible type' 'variable "{0}" has a default value calculated with "{1}" which has incompatible type'
).format(self.path, self.variable) ).format(path, self.variable)
raise DictConsistencyError(msg, 67, self.xmlfiles) raise DictConsistencyError(msg, 67, self.xmlfiles)
params = self.get_params( params = self.get_params(
objectspace, objectspace,
path,
variable_in_calculation_path, variable_in_calculation_path,
variable_in_calculation, variable_in_calculation,
variable_in_calculation_identifier, variable_in_calculation_identifier,
@ -785,12 +796,13 @@ class VariablePropertyCalculation(_VariableCalculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
( (
variable_in_calculation_path, variable_in_calculation_path,
variable_in_calculation, variable_in_calculation,
variable_in_calculation_identifier, variable_in_calculation_identifier,
) = self.get_variable(objectspace) ) = self.get_variable(objectspace, path)
if ( if (
# self.default is not undefined and # self.default is not undefined and
not variable_in_calculation not variable_in_calculation
@ -804,11 +816,12 @@ class VariablePropertyCalculation(_VariableCalculation):
msg = _( msg = _(
'the variable "{0}" is waiting for a boolean as "{1}" but the attribute "default" is not a boolean ("{2}")' 'the variable "{0}" is waiting for a boolean as "{1}" but the attribute "default" is not a boolean ("{2}")'
) )
msg = msg.format(self.path, self.attribute_name, default) msg = msg.format(path, self.attribute_name, default)
raise DictConsistencyError(msg, 79, self.xmlfiles) raise DictConsistencyError(msg, 79, self.xmlfiles)
return self.get_default_value_optional(objectspace, default) return self.get_default_value_optional(objectspace, default)
params = self.get_params( params = self.get_params(
objectspace, objectspace,
path,
variable_in_calculation_path, variable_in_calculation_path,
variable_in_calculation, variable_in_calculation,
variable_in_calculation_identifier, variable_in_calculation_identifier,
@ -825,12 +838,12 @@ class VariablePropertyCalculation(_VariableCalculation):
if self.version == "1.0": if self.version == "1.0":
msg = _( msg = _(
'"when" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"' '"when" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"'
).format(self.attribute_name, self.path) ).format(self.attribute_name, path)
raise DictConsistencyError(msg, 103, variable.xmlfiles) raise DictConsistencyError(msg, 103, variable.xmlfiles)
if self.when_not is not undefined: if self.when_not is not undefined:
msg = _( msg = _(
'the variable "{0}" has an invalid attribute "{1}", "when" and "when_not" cannot set together' 'the variable "{0}" has an invalid attribute "{1}", "when" and "when_not" cannot set together'
).format(self.path, self.attribute_name) ).format(path, self.attribute_name)
raise DictConsistencyError(msg, 31, variable.xmlfiles) raise DictConsistencyError(msg, 31, variable.xmlfiles)
when = self.when when = self.when
inverse = False inverse = False
@ -838,7 +851,7 @@ class VariablePropertyCalculation(_VariableCalculation):
if self.version == "1.0": if self.version == "1.0":
msg = _( msg = _(
'"when_not" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"' '"when_not" is not allowed in format version 1.0 for attribute "{0}" for variable "{1}"'
).format(self.attribute_name, self.path) ).format(self.attribute_name, path)
raise DictConsistencyError(msg, 104, variable.xmlfiles) raise DictConsistencyError(msg, 104, variable.xmlfiles)
when = self.when_not when = self.when_not
inverse = True inverse = True
@ -849,7 +862,7 @@ class VariablePropertyCalculation(_VariableCalculation):
if variable.type != "boolean": if variable.type != "boolean":
msg = _( msg = _(
'"when" or "when_not" is mandatory for the not boolean variable "{0}" in attribute "{1}"' '"when" or "when_not" is mandatory for the not boolean variable "{0}" in attribute "{1}"'
).format(self.path, self.attribute_name) ).format(path, self.attribute_name)
raise DictConsistencyError(msg, 106, variable.xmlfiles) raise DictConsistencyError(msg, 106, variable.xmlfiles)
when = True when = True
inverse = False inverse = False
@ -872,6 +885,7 @@ class InformationCalculation(Calculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
params = { params = {
None: [ None: [
@ -882,10 +896,10 @@ class InformationCalculation(Calculation):
] ]
} }
if self.variable: if self.variable:
if self.ori_path is None: # if self.ori_path is None:
path = self.path # path = self.path
else: # else:
path = self.ori_path # path = self.ori_path
variable, identifier = objectspace.paths.get_with_dynamic( variable, identifier = objectspace.paths.get_with_dynamic(
self.variable, self.variable,
path, path,
@ -931,6 +945,7 @@ class IdentifierCalculation(_IdentifierCalculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
identifier = {"type": "identifier"} identifier = {"type": "identifier"}
if self.identifier is not None: if self.identifier is not None:
@ -992,11 +1007,12 @@ class IndexCalculation(Calculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
if self.path not in objectspace.followers: if path not in objectspace.followers:
msg = _( msg = _(
'the variable "{0}" is not a follower, so cannot have index type for "{1}"' 'the variable "{0}" is not a follower, so cannot have index type for "{1}"'
).format(self.path, self.attribute_name) ).format(path, self.attribute_name)
raise DictConsistencyError(msg, 60, self.xmlfiles) raise DictConsistencyError(msg, 60, self.xmlfiles)
return { return {
"function": "calc_value", "function": "calc_value",
@ -1011,6 +1027,7 @@ class NamespaceCalculation(Calculation):
def to_function( def to_function(
self, self,
objectspace, objectspace,
path,
) -> dict: ) -> dict:
namespace = self.namespace namespace = self.namespace
if namespace: if namespace:

View file

@ -384,7 +384,7 @@ class Common:
function, function,
) -> str: ) -> str:
"""Generate calculated value""" """Generate calculated value"""
child = function.to_function(self.objectspace) child = function.to_function(self.objectspace, self.elt.path)
if isinstance(child, str): if isinstance(child, str):
return self.convert_str(child) return self.convert_str(child)
elif not isinstance(child, dict): elif not isinstance(child, dict):

View file

@ -43,6 +43,21 @@ def type_variable(test_name):
with variables_file.open('r') as fh: with variables_file.open('r') as fh:
loaded_configuration = load(fh) loaded_configuration = load(fh)
assert loaded_configuration == loads(dumps(configuration)), f"error in file {variables_file}" assert loaded_configuration == loads(dumps(configuration)), f"error in file {variables_file}"
#
print('--------------')
print('--------------')
print('--------------')
print(config.value.get())
config.property.read_write()
print(config.value.get())
variables_file = result / "variables_rw.json"
configuration = dict(config_to_dict(config.value.get()))
if not variables_file.is_file():
with variables_file.open('w') as fh:
dump(configuration, fh, indent=4)
with variables_file.open('r') as fh:
loaded_configuration = load(fh)
assert loaded_configuration == loads(dumps(configuration)), f"error in file {variables_file}"
def test_type_variable(): def test_type_variable():