diff --git a/src/rougail/error.py b/src/rougail/error.py index aa2b27c0a..6f237b843 100644 --- a/src/rougail/error.py +++ b/src/rougail/error.py @@ -79,3 +79,15 @@ class UpgradeError(Exception): class NotFoundError(Exception): "not found error" pass + +## ---- specific exceptions ---- + +class VariableCalculationDependencyError(Exception): + """When an 'optional=true' attribute is set, and + the target variable doesn't exists. + """ + def __init__(self, msg, errno, xmlfiles): + if xmlfiles: + msg = _(f"{msg} in {display_xmlfiles(xmlfiles)}") + super().__init__(msg) + self.errno = errno diff --git a/src/rougail/object_model.py b/src/rougail/object_model.py index cab67681d..e428866c2 100644 --- a/src/rougail/object_model.py +++ b/src/rougail/object_model.py @@ -31,7 +31,7 @@ from pydantic import ( ) from tiramisu import undefined from .utils import get_jinja_variable_to_param, get_realpath -from .error import DictConsistencyError +from .error import DictConsistencyError, VariableCalculationDependencyError BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None] PROPERTY_ATTRIBUTE = ["frozen", "hidden", "disabled", "mandatory"] @@ -383,8 +383,12 @@ class VariableCalculation(Calculation): self.variable, self.path_prefix, path, self.version, self.namespace, self.xmlfiles ) if not variable: - msg = f'Variable not found "{self.variable}" for attribut "{self.attribute_name}" for variable "{self.path}"' - raise DictConsistencyError(msg, 88, self.xmlfiles) + if self.optional: + msg = f'the dependent variable was not found "{self.optional}" for variable "{self.path}"' + raise VariableCalculationDependencyError(msg, 90, self.xmlfiles) + else: + msg = f'Variable not found "{self.variable}" for attribute "{self.attribute_name}" for variable "{self.path}"' + raise DictConsistencyError(msg, 88, self.xmlfiles) if not isinstance(variable, objectspace.variable): # FIXME remove the pfff raise Exception("pfff it's a family") diff --git a/src/rougail/tiramisureflector.py b/src/rougail/tiramisureflector.py index 445cd562c..d6e23e335 100644 --- a/src/rougail/tiramisureflector.py +++ b/src/rougail/tiramisureflector.py @@ -33,7 +33,7 @@ from json import dumps from os.path import isfile, basename from .i18n import _ -from .error import DictConsistencyError +from .error import DictConsistencyError, VariableCalculationDependencyError from .utils import normalize_family from .object_model import Calculation, CONVERT_OPTION @@ -447,7 +447,11 @@ class Variable(Common): if not hasattr(self.elt, "default"): print('FIXME CA EXISTE!!!') if hasattr(self.elt, "default") and self.elt.default is not None: - keys["default"] = self.populate_calculation(self.elt.default) + try: + keys["default"] = self.populate_calculation(self.elt.default) + except VariableCalculationDependencyError: + pass + # mettre dans tous les populate_calculation() if self.elt.path in self.objectspace.default_multi: keys["default_multi"] = self.populate_calculation(self.objectspace.default_multi[self.elt.path]) if self.elt.validators: diff --git a/tests/dictionaries/90_optional_parameter_in_variable_default/__init__.py b/tests/dictionaries/90_optional_parameter_in_variable_default/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/90_optional_parameter_in_variable_default/dictionaries/rougail/00-base.yml b/tests/dictionaries/90_optional_parameter_in_variable_default/dictionaries/rougail/00-base.yml new file mode 100644 index 000000000..b65bc9e7d --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_default/dictionaries/rougail/00-base.yml @@ -0,0 +1,13 @@ +version: 1.1 +#my_variable: +# multi: true +# default: +# - val1 +# - val2 +my_calculated_variable: + multi: true + default: + type: variable + variable: rougail.my_variable + optional: true + diff --git a/tests/dictionaries/90_optional_parameter_in_variable_default/readme.txt b/tests/dictionaries/90_optional_parameter_in_variable_default/readme.txt new file mode 100644 index 000000000..bd641280c --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_default/readme.txt @@ -0,0 +1,32 @@ + --- + version: 1.1 + var1: + default: + type: jinja + jinja: | + val + params: + var1: + type: variable + variable: _.var2 + optional: true + + + --- + version: 1.1 + var1: + default: + type: variable + variable: _.var2 + optional: true + +--- + le 1er dico fonctionne + si on fait une variable dans un parametre on peut la mettre optionnelle (si la variable est déclaré ca passe la variable en parametre, si la variable n'existe pas ca ne passe pas le parametre) + dans notre cas la variable n'existe pas donc ne passe pas le parametre + dans le 2eme ca on ne fait pas un calcul via jinja mais récupère directement la valeur de la variable + sauf que le optional n'existe pas pour un calcul (juste pour un parametre) + faudrait : + 1/ ajouter cette possibilité + voir s'il n'y a pas d'autres manque + (c'étaot ele 2) diff --git a/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/base.py b/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/base.py new file mode 100644 index 000000000..9a8691b8d --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/base.py @@ -0,0 +1,10 @@ +from tiramisu import * +from tiramisu.setting import ALLOWED_LEADER_PROPERTIES +from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription +load_functions('tests/dictionaries/../eosfunc/test.py') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_2 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2], properties=frozenset({"standard"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1]) diff --git a/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/multi.py b/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/multi.py new file mode 100644 index 000000000..f11223bfd --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_default/tiramisu/multi.py @@ -0,0 +1,14 @@ +from tiramisu import * +from tiramisu.setting import ALLOWED_LEADER_PROPERTIES +from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription +load_functions('tests/dictionaries/../eosfunc/test.py') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_3 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[option_3], properties=frozenset({"standard"})) +optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"})) +option_6 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_5 = OptionDescription(name="rougail", doc="rougail", children=[option_6], properties=frozenset({"standard"})) +optiondescription_4 = OptionDescription(name="2", doc="2", children=[optiondescription_5], properties=frozenset({"standard"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_4]) diff --git a/tests/dictionaries/90_optional_parameter_in_variable_exists/__init__.py b/tests/dictionaries/90_optional_parameter_in_variable_exists/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/90_optional_parameter_in_variable_exists/dictionaries/rougail/00-base.yml b/tests/dictionaries/90_optional_parameter_in_variable_exists/dictionaries/rougail/00-base.yml new file mode 100644 index 000000000..382366bc4 --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_exists/dictionaries/rougail/00-base.yml @@ -0,0 +1,13 @@ +version: 1.1 +my_variable: + multi: true + default: + - val1 + - val2 +my_calculated_variable: + multi: true + default: + type: variable + variable: rougail.my_variable + optional: true + diff --git a/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/base.py b/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/base.py new file mode 100644 index 000000000..1d6d218ea --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/base.py @@ -0,0 +1,11 @@ +from tiramisu import * +from tiramisu.setting import ALLOWED_LEADER_PROPERTIES +from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription +load_functions('tests/dictionaries/../eosfunc/test.py') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_2 = StrOption(name="my_variable", doc="my_variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) +option_3 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_2)))), properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_3], properties=frozenset({"standard"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1]) diff --git a/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/multi.py b/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/multi.py new file mode 100644 index 000000000..a6fb04cab --- /dev/null +++ b/tests/dictionaries/90_optional_parameter_in_variable_exists/tiramisu/multi.py @@ -0,0 +1,16 @@ +from tiramisu import * +from tiramisu.setting import ALLOWED_LEADER_PROPERTIES +from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription +load_functions('tests/dictionaries/../eosfunc/test.py') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_3 = StrOption(name="my_variable", doc="my_variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) +option_4 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_3)))), properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[option_3, option_4], properties=frozenset({"standard"})) +optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"})) +option_7 = StrOption(name="my_variable", doc="my_variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) +option_8 = StrOption(name="my_calculated_variable", doc="my_calculated_variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_7)))), properties=frozenset({"mandatory", "notempty", "standard"})) +optiondescription_6 = OptionDescription(name="rougail", doc="rougail", children=[option_7, option_8], properties=frozenset({"standard"})) +optiondescription_5 = OptionDescription(name="2", doc="2", children=[optiondescription_6], properties=frozenset({"standard"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_5])