bump: version 1.2.0a56 → 1.2.0a57

This commit is contained in:
egarette@silique.fr 2026-01-16 08:48:46 +01:00
parent 1ee82bede9
commit f9c73783c5
12 changed files with 120 additions and 81 deletions

View file

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

View file

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

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail-base"
version = "1.2.0a56"
version = "1.2.0a57"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md"
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]
name = "rougail"
version = "1.2.0a56"
version = "1.2.0a57"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
description = "A consistency handling system that was initially designed in the configuration management"
classifiers = [
@ -18,7 +18,7 @@ classifiers = [
dependencies = [
"ruamel.yaml ~= 0.18.6",
"pydantic ~= 2.9.2",
"rougail-base == 1.2.0a56",
"rougail-base == 1.2.0a57",
]
[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:
calculation_copy = calculation.model_copy()
calculation_copy.attribute_name = "frozen"
calculation_copy.ori_path = calculation_copy.path
calculation_copy.path = path
# calculation_copy.ori_path = calculation_copy.path
# calculation_copy.path = path
value.append(calculation_copy)
if len(value) == 1:
value = value[0]

View file

@ -147,7 +147,7 @@ class Annotator(Walk): # pylint: disable=R0903
variable.type = "integer"
elif isinstance(variable.default, VariableCalculation):
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:
self._default_variable_copy_informations(
@ -236,7 +236,7 @@ class Annotator(Walk): # pylint: disable=R0903
variable.default, VariableCalculation
):
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.multi is None:

View file

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

View file

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

View file

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

View file

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

View file

@ -43,6 +43,21 @@ def type_variable(test_name):
with variables_file.open('r') as fh:
loaded_configuration = load(fh)
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():