From b3917cb86262d8f062fb713515ddcb78b8772a4c Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 2 Sep 2026 18:59:21 +0200 Subject: [PATCH] fix: a type could be a dynamic family --- src/rougail/convert/collect.py | 4 +++- src/rougail/convert/convert.py | 1 + tests/test_types.py | 8 ++++++++ .../family_root_dynfamily/namespace_tiramisu.py | 15 +++++++++++++++ .../namespace_variables.json | 8 ++++++++ .../namespace_variables_rw.json | 8 ++++++++ .../result/family_root_dynfamily/tiramisu.py | 16 ++++++++++++++++ .../result/family_root_dynfamily/variables.json | 8 ++++++++ .../family_root_dynfamily/variables_rw.json | 8 ++++++++ .../family_root_dynfamily/00_structure.yml | 13 +++++++++++++ .../types/family_root_dynfamily/00_structure.yml | 13 +++++++++++++ 11 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 tests/types/result/family_root_dynfamily/namespace_tiramisu.py create mode 100644 tests/types/result/family_root_dynfamily/namespace_variables.json create mode 100644 tests/types/result/family_root_dynfamily/namespace_variables_rw.json create mode 100644 tests/types/result/family_root_dynfamily/tiramisu.py create mode 100644 tests/types/result/family_root_dynfamily/variables.json create mode 100644 tests/types/result/family_root_dynfamily/variables_rw.json create mode 100644 tests/types/structures/family_root_dynfamily/00_structure.yml create mode 100644 tests/types/types/family_root_dynfamily/00_structure.yml diff --git a/src/rougail/convert/collect.py b/src/rougail/convert/collect.py index ea0feaa59..155715999 100644 --- a/src/rougail/convert/collect.py +++ b/src/rougail/convert/collect.py @@ -54,7 +54,7 @@ class CollectFamily: elif "variable" in self.parameters: self.name += "{{ identifier }}" self.path += "{{ identifier }}" - elif self.raises: + elif self.raises and not self.is_type: msg = f'dynamic family name must have "{{{{ identifier }}}}" in his name for "{self.path}"' raise DictConsistencyError(msg, 13, self.sources) if self.version == "1.0": @@ -501,6 +501,7 @@ class Collect(CollectType, CollectFamily, CollectVariable): parent_option: Optional["Collect"], *, raises: bool = True, + is_type: bool = False, test_exists: bool = True, ) -> None: self.sources_types = None @@ -511,6 +512,7 @@ class Collect(CollectType, CollectFamily, CollectVariable): else: path = f"{subpath}.{name}" self.raises = raises + self.is_type = is_type self.test_exists = test_exists if self.raises and name.startswith("_"): msg = f'the variable or family "{self.path}" is incorrect, it must not starts with "_" character' diff --git a/src/rougail/convert/convert.py b/src/rougail/convert/convert.py index d377df00a..bbdd4ee81 100644 --- a/src/rougail/convert/convert.py +++ b/src/rougail/convert/convert.py @@ -293,6 +293,7 @@ class ParserVariable: obj, comment, parent_option, + is_type=self.loaded_custom_types is not None, ) if option.option_type == "family": parser = self.parse_family diff --git a/tests/test_types.py b/tests/test_types.py index 3d46658f6..a9a20f1c3 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -129,6 +129,14 @@ def test_type_dynfamily_namespace(): type_variable("family_dynfamily", namespace=True) +def test_type_root_dynfamily(): + type_variable("family_root_dynfamily") + + +def test_type_root_dynfamily_namespace(): + type_variable("family_root_dynfamily", namespace=True) + + def test_type_family_subfamily_add(): type_variable("family_subfamily_add") diff --git a/tests/types/result/family_root_dynfamily/namespace_tiramisu.py b/tests/types/result/family_root_dynfamily/namespace_tiramisu.py new file mode 100644 index 000000000..a94362ab2 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/namespace_tiramisu.py @@ -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 +try: + groups.namespace +except: + groups.addgroup('namespace') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_1 = StrOption(name="a_variable", doc="A variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/structures/family_root_dynfamily/00_structure.yml'], 'type': 'string'}) +option_3 = StrOption(name="a_first_variable", doc="A first variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_root_dynfamily/00_structure.yml', 'tests/types/structures/family_root_dynfamily/00_structure.yml'], 'type': 'string'}) +optiondescription_2 = ConvertDynOptionDescription(name="my_family_{{ identifier }}", doc="My family type", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_1)))), children=[option_3], properties=frozenset({"standard"}), informations={'dynamic_variable': 'a_variable', 'ymlfiles': ['tests/types/types/family_root_dynfamily/00_structure.yml', 'tests/types/structures/family_root_dynfamily/00_structure.yml']}) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, optiondescription_2]) diff --git a/tests/types/result/family_root_dynfamily/namespace_variables.json b/tests/types/result/family_root_dynfamily/namespace_variables.json new file mode 100644 index 000000000..afb6ad293 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/namespace_variables.json @@ -0,0 +1,8 @@ +{ + "a_variable": [ + "val1", + "val2" + ], + "my_family_val1.a_first_variable": "val1", + "my_family_val2.a_first_variable": "val2" +} \ No newline at end of file diff --git a/tests/types/result/family_root_dynfamily/namespace_variables_rw.json b/tests/types/result/family_root_dynfamily/namespace_variables_rw.json new file mode 100644 index 000000000..afb6ad293 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/namespace_variables_rw.json @@ -0,0 +1,8 @@ +{ + "a_variable": [ + "val1", + "val2" + ], + "my_family_val1.a_first_variable": "val1", + "my_family_val2.a_first_variable": "val2" +} \ No newline at end of file diff --git a/tests/types/result/family_root_dynfamily/tiramisu.py b/tests/types/result/family_root_dynfamily/tiramisu.py new file mode 100644 index 000000000..01f0bdec5 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/tiramisu.py @@ -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 +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="a_variable", doc="A variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/structures/family_root_dynfamily/00_structure.yml'], 'type': 'string'}) +option_5 = StrOption(name="a_first_variable", doc="A first variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_root_dynfamily/00_structure.yml', 'tests/types/structures/family_root_dynfamily/00_structure.yml'], 'type': 'string'}) +optiondescription_4 = ConvertDynOptionDescription(name="my_family_{{ identifier }}", doc="My family type", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_3)))), children=[option_5], properties=frozenset({"standard"}), informations={'dynamic_variable': 'ns2.a_variable', 'ymlfiles': ['tests/types/types/family_root_dynfamily/00_structure.yml', 'tests/types/structures/family_root_dynfamily/00_structure.yml']}) +optiondescription_2 = OptionDescription(name="ns2", doc="NS2", group_type=groups.namespace, children=[option_3, optiondescription_4], properties=frozenset({"standard"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_2]) diff --git a/tests/types/result/family_root_dynfamily/variables.json b/tests/types/result/family_root_dynfamily/variables.json new file mode 100644 index 000000000..c2ad009c5 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/variables.json @@ -0,0 +1,8 @@ +{ + "ns2.a_variable": [ + "val1", + "val2" + ], + "ns2.my_family_val1.a_first_variable": "val1", + "ns2.my_family_val2.a_first_variable": "val2" +} \ No newline at end of file diff --git a/tests/types/result/family_root_dynfamily/variables_rw.json b/tests/types/result/family_root_dynfamily/variables_rw.json new file mode 100644 index 000000000..c2ad009c5 --- /dev/null +++ b/tests/types/result/family_root_dynfamily/variables_rw.json @@ -0,0 +1,8 @@ +{ + "ns2.a_variable": [ + "val1", + "val2" + ], + "ns2.my_family_val1.a_first_variable": "val1", + "ns2.my_family_val2.a_first_variable": "val2" +} \ No newline at end of file diff --git a/tests/types/structures/family_root_dynfamily/00_structure.yml b/tests/types/structures/family_root_dynfamily/00_structure.yml new file mode 100644 index 000000000..8f3ed0da2 --- /dev/null +++ b/tests/types/structures/family_root_dynfamily/00_structure.yml @@ -0,0 +1,13 @@ +%YAML 1.2 +--- +version: 1.1 + +a_variable: # A variable + - val1 + - val2 + +my_family_{{ identifier }}: + type: my_family_type + dynamic: + variable: _.a_variable +... diff --git a/tests/types/types/family_root_dynfamily/00_structure.yml b/tests/types/types/family_root_dynfamily/00_structure.yml new file mode 100644 index 000000000..5f1d590a6 --- /dev/null +++ b/tests/types/types/family_root_dynfamily/00_structure.yml @@ -0,0 +1,13 @@ +%YAML 1.2 +--- +version: 1.1 + +my_family_type: + description: My family type + dynamic: [] + + a_first_variable: + description: A first variable + default: + type: identifier +...