feat: active warnings for validators

This commit is contained in:
egarette@silique.fr 2025-11-01 10:48:07 +01:00
parent d3477d6241
commit 656df6068f
34 changed files with 278 additions and 3 deletions

View file

@ -242,11 +242,15 @@ class Calculation(BaseModel):
ori_path: Optional[str] = None
default_values: Any = None
namespace: Optional[str]
warnings: Optional[bool] = None
xmlfiles: List[str]
model_config = ConfigDict(extra="forbid")
def get_params(self, objectspace):
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}"')
raise DictConsistencyError(msg, 83, xmlfiles)
if not self.params:
return {}
if self.ori_path is None:
@ -334,6 +338,8 @@ class JinjaCalculation(Calculation):
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(
path,
self.jinja,
@ -1023,6 +1029,7 @@ class Variable(BaseModel):
choices: Optional[Union[List[BASETYPE_CALC], Calculation]] = None
multi: Optional[bool] = None
validators: Optional[List[Calculation]] = None
warnings: bool = False
# value
default: Union[List[BASETYPE_CALC], BASETYPE_CALC] = None
secret_manager: Optional[JinjaCalculation] = None

View file

@ -395,8 +395,8 @@ class Common:
if kwargs:
ret += ", kwargs={" + ", ".join(kwargs) + "}"
ret += ")"
if hasattr(child, "warnings_only"):
ret += f", warnings_only={child.warnings_only}"
if "warnings_only" in child:
ret += f", warnings_only={child['warnings_only']}"
if "help" in child:
ret += f", help_function=func['{child['help']}']"
ret = ret + ")"
@ -497,6 +497,8 @@ class Variable(Common):
pass
if self.elt.validators:
keys["validators"] = self.populate_calculation(self.elt.validators)
if self.elt.warnings:
keys["warnings_only"] = True
for key, value in (
CONVERT_OPTION.get(self.elt.type, {}).get("initkwargs", {}).items()
):

View file

@ -0,0 +1,6 @@
{
"rougail.int": {
"owner": "default",
"value": 1000
}
}

View file

@ -0,0 +1,3 @@
{
"rougail.int": 1000
}

View file

@ -0,0 +1,6 @@
{
"rougail.int": {
"owner": "default",
"value": 1000
}
}

View file

@ -0,0 +1,3 @@
{
"rougail.int": 1000
}

View file

@ -0,0 +1,16 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
try:
groups.namespace
except:
groups.addgroup('namespace')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
dict_env['validators_rougail.int'] = "{% if _.int > 100 %}\n value is too high\n{% endif %}"
option_2 = IntOption(name="int", doc="An integer", default=1000, validators=[Calculation(func['valid_with_jinja'], Params((), kwargs={'__internal_jinja': ParamValue("validators_rougail.int"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/04_5validators_warnings/rougail/00-base.yml']), '__internal_attribute': ParamValue("validators"), '__internal_variable': ParamValue("rougail.int"), '_.int': ParamSelfOption(whole=False)}), warnings_only=True)], properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/04_5validators_warnings/rougail/00-base.yml'], 'type': 'integer'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"standard"}), informations={'ymlfiles': ['']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,11 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
dict_env['validators_int'] = "{% if _.int > 100 %}\n value is too high\n{% endif %}"
option_1 = IntOption(name="int", doc="An integer", default=1000, validators=[Calculation(func['valid_with_jinja'], Params((), kwargs={'__internal_jinja': ParamValue("validators_int"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/04_5validators_warnings/rougail/00-base.yml']), '__internal_attribute': ParamValue("validators"), '__internal_variable': ParamValue("int"), '_.int': ParamSelfOption(whole=False)}), warnings_only=True)], properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/04_5validators_warnings/rougail/00-base.yml'], 'type': 'integer'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1])

View file

@ -0,0 +1,6 @@
{
"rougail.int": {
"owner": "default",
"value": 1000
}
}

View file

@ -0,0 +1,3 @@
{
"rougail.int": 1000
}

View file

@ -0,0 +1,6 @@
{
"rougail.int": {
"owner": "default",
"value": 1000
}
}

View file

@ -0,0 +1,3 @@
{
"rougail.int": 1000
}

View file

@ -0,0 +1,15 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
try:
groups.namespace
except:
groups.addgroup('namespace')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_2 = IntOption(name="int", doc="An integer", default=1000, warnings_only=True, min_integer=10, max_integer=100, properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/04_5validators_warnings_all/rougail/00-base.yml'], 'type': 'integer'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"standard"}), informations={'ymlfiles': ['']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,10 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_1 = IntOption(name="int", doc="An integer", default=1000, warnings_only=True, min_integer=10, max_integer=100, properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/04_5validators_warnings_all/rougail/00-base.yml'], 'type': 'integer'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1])

View file

@ -0,0 +1,11 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_2 = StrOption(name="var", doc="A dynamic variable", properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((), kwargs={'prop': ParamValue("disabled"), 'value': ParamIdentifier(), 'when': ParamValue("val1"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_suffix_disabled/rougail/00-base.yml'], 'type': 'string'})
optiondescription_1 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="dyn{{ identifier }}", identifiers=["val1", "val2"], children=[option_2], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_suffix_disabled/rougail/00-base.yml']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,18 @@
{
"rougail.dynval1.var1": {
"owner": "default",
"value": null
},
"rougail.dynval1.var2": {
"owner": "default",
"value": null
},
"rougail.dynval2.var1": {
"owner": "default",
"value": null
},
"rougail.dynval2.var2": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1,6 @@
{
"rougail.dynval1.var1": null,
"rougail.dynval1.var2": null,
"rougail.dynval2.var1": null,
"rougail.dynval2.var2": null
}

View file

@ -0,0 +1,18 @@
{
"rougail.dynval1.var1": {
"owner": "default",
"value": null
},
"rougail.dynval1.var2": {
"owner": "default",
"value": null
},
"rougail.dynval2.var1": {
"owner": "default",
"value": null
},
"rougail.dynval2.var2": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1 @@
["rougail.dynval1.var1", "rougail.dynval1.var2", "rougail.dynval2.var1", "rougail.dynval2.var2"]

View file

@ -0,0 +1,6 @@
{
"rougail.dynval1.var1": null,
"rougail.dynval1.var2": null,
"rougail.dynval2.var1": null,
"rougail.dynval2.var2": null
}

View file

@ -0,0 +1,17 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
try:
groups.namespace
except:
groups.addgroup('namespace')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_3 = StrOption(name="var1", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml'], 'type': 'string'})
option_4 = StrOption(name="var2", doc="A new variable", properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((), kwargs={'value': ParamOption(option_3), 'prop': ParamValue("disabled"), 'when': ParamValue("val1"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml'], 'type': 'string'})
optiondescription_2 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic famify for {{ identifier }}", identifiers=["val1", "val2"], children=[option_3, option_4], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml']})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[optiondescription_2], properties=frozenset({"basic"}), informations={'ymlfiles': ['']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,12 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_2 = StrOption(name="var1", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml'], 'type': 'string'})
option_3 = StrOption(name="var2", doc="A new variable", properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((), kwargs={'value': ParamOption(option_2), 'prop': ParamValue("disabled"), 'when': ParamValue("val1"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml'], 'type': 'string'})
optiondescription_1 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic famify for {{ identifier }}", identifiers=["val1", "val2"], children=[option_2, option_3], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled/rougail/00-base.yml']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,14 @@
{
"rougail.dynval1.var1": {
"owner": "default",
"value": null
},
"rougail.dynval2.var1": {
"owner": "default",
"value": null
},
"rougail.var2": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1,5 @@
{
"rougail.dynval1.var1": null,
"rougail.dynval2.var1": null,
"rougail.var2": null
}

View file

@ -0,0 +1,14 @@
{
"rougail.dynval1.var1": {
"owner": "default",
"value": null
},
"rougail.dynval2.var1": {
"owner": "default",
"value": null
},
"rougail.var2": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1 @@
["rougail.dynval1.var1", "rougail.dynval2.var1", "rougail.var2"]

View file

@ -0,0 +1,5 @@
{
"rougail.dynval1.var1": null,
"rougail.dynval2.var1": null,
"rougail.var2": null
}

View file

@ -0,0 +1,17 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
try:
groups.namespace
except:
groups.addgroup('namespace')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_3 = StrOption(name="var1", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml'], 'type': 'string'})
optiondescription_2 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic famify for {{ identifier }}", identifiers=["val1", "val2"], children=[option_3], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml']})
option_4 = StrOption(name="var2", doc="A new variable", properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((), kwargs={'value': ParamDynOption(option_3, ["val1"]), 'prop': ParamValue("disabled"), 'when': ParamValue("val1"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml'], 'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[optiondescription_2, option_4], properties=frozenset({"basic"}), informations={'ymlfiles': ['']})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,12 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
from re import compile as re_compile
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
load_functions('../rougail-tests/funcs/test.py')
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
option_2 = StrOption(name="var1", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml'], 'type': 'string'})
optiondescription_1 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic famify for {{ identifier }}", identifiers=["val1", "val2"], children=[option_2], properties=frozenset({"basic"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml']})
option_3 = StrOption(name="var2", doc="A new variable", properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((), kwargs={'value': ParamDynOption(option_2, ["val1"]), 'prop': ParamValue("disabled"), 'when': ParamValue("val1"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_variable_disabled_outside/rougail/00-base.yml'], 'type': 'string'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, option_3])

View file

@ -0,0 +1,19 @@
%YAML 1.2
---
version: 1.1
dyn{{ identifier }}:
description: A dynamic famify for {{ identifier }}
dynamic:
- val1
- val2
var1:
description: A dynamic variable
var4:
description: A new variable
disabled:
variable: _.dyn{{ identifier }}.var1
when: 'val1'
...

View file

@ -47,7 +47,7 @@ excludes = set([
])
test_ok -= excludes
test_raise -= excludes
# test_ok = ['02_0tags']
#test_ok = ['04_5validators_warnings_all']
#test_ok = []
# test_raise = ['80unknown_default_variable_inside_dynamic_family']
#test_raise = []