Compare commits

..

No commits in common. "26541410022bef10a053cec9d60e48f74ec26314" and "d35fe16cd9ed975ab4f6cb0eb427ce4e3219fa00" have entirely different histories.

55 changed files with 67 additions and 661 deletions

View file

@ -1,9 +1,3 @@
## 1.2.0a12 (2025-03-19)
### Feat
- add rougail secret_manager
## 1.2.0a11 (2025-02-17) ## 1.2.0a11 (2025-02-17)
### Fix ### Fix

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail" name = "rougail"
version = "1.2.0a12" version = "1.2.0a11"
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

@ -43,7 +43,7 @@ def tiramisu_display_name(
"""Replace the Tiramisu display_name function to display path + description""" """Replace the Tiramisu display_name function to display path + description"""
doc = kls._get_information(subconfig, "doc", None) doc = kls._get_information(subconfig, "doc", None)
comment = f" ({doc})" if doc and doc != kls.impl_getname() else "" comment = f" ({doc})" if doc and doc != kls.impl_getname() else ""
if "{{ identifier }}" in comment and subconfig.identifiers: if "{{ identifier }}" in comment:
comment = comment.replace("{{ identifier }}", str(subconfig.identifiers[-1])) comment = comment.replace("{{ identifier }}", str(subconfig.identifiers[-1]))
path = kls.impl_getpath() path = kls.impl_getpath()
if "{{ identifier }}" in path and subconfig.identifiers: if "{{ identifier }}" in path and subconfig.identifiers:

View file

@ -136,9 +136,7 @@ class Annotator(Walk):
) )
if family.version == "1.0" and "{{ suffix }}" in path: if family.version == "1.0" and "{{ suffix }}" in path:
path = path.replace("{{ suffix }}", "{{ identifier }}") path = path.replace("{{ suffix }}", "{{ identifier }}")
self.objectspace.dynamics_variable.setdefault(path, []).append( self.objectspace.dynamics_variable.setdefault(path, []).append(family.path)
family.path
)
self.objectspace.informations.add(family.path, "dynamic_variable", path) self.objectspace.informations.add(family.path, "dynamic_variable", path)
def change_modes(self): def change_modes(self):
@ -343,7 +341,7 @@ class Annotator(Walk):
if self._has_mode(variable): if self._has_mode(variable):
msg = _( msg = _(
'the variable "{0}" is in "{1}" mode but family has the higher family mode "{2}"' 'the variable "{0}" is in "{1}" mode but family has the higher family mode "{2}"'
).format(variable.path, variable_mode, family_mode) ).format(variable.name, variable_mode, family_mode)
raise DictConsistencyError(msg, 61, variable.xmlfiles) raise DictConsistencyError(msg, 61, variable.xmlfiles)
self._set_auto_mode(variable, family_mode) self._set_auto_mode(variable, family_mode)
if not variable.mode: if not variable.mode:

View file

@ -69,28 +69,12 @@ class Annotator(Walk): # pylint: disable=R0903
bool: "boolean", bool: "boolean",
float: "float", float: "float",
} }
self.verify_secret_managers()
self.verify_choices() self.verify_choices()
self.convert_variable() self.convert_variable()
self.convert_test() self.convert_test()
self.convert_examples() self.convert_examples()
self.convert_help() self.convert_help()
def verify_secret_managers(self):
for variable in self.get_variables():
if not variable.secret_manager:
continue
path = variable.path
if variable.type not in ["unix_user", "secret"]:
msg = _('only "unix_user" or "secret" variable type can have "secret_manager" attribute, but "{0}" has type "{1}"')
raise DictConsistencyError(msg.format(path, variable.type), 56, variable.xmlfiles)
if variable.multi and path not in self.objectspace.leaders:
msg = _('the variable "{0}" has attribute "secret_manager" but is a multi variable')
raise DictConsistencyError(msg.format(path), 57, variable.xmlfiles)
if variable.default is not None:
msg = _('the variable "{0}" has attribute "secret_manager" so must not have default value')
raise DictConsistencyError(msg.format(path), 59, variable.xmlfiles)
def convert_variable(self): def convert_variable(self):
"""convert variable""" """convert variable"""
for variable in self.get_variables(): for variable in self.get_variables():
@ -146,9 +130,7 @@ class Annotator(Walk): # pylint: disable=R0903
): ):
return return
# copy type and params # copy type and params
calculated_variable, identifier = variable.default.get_variable( calculated_variable, identifier = variable.default.get_variable(self.objectspace)
self.objectspace
)
if calculated_variable is None: if calculated_variable is None:
return return
variable.type = calculated_variable.type variable.type = calculated_variable.type

View file

@ -73,7 +73,8 @@ def get_level(module):
class _RougailConfig: class _RougailConfig:
def __init__(self, backward_compatibility: bool, add_extra_options: bool): def __init__(self, backward_compatibility: bool,
add_extra_options: bool):
self.backward_compatibility = backward_compatibility self.backward_compatibility = backward_compatibility
self.add_extra_options = add_extra_options self.add_extra_options = add_extra_options
self.root = None self.root = None
@ -85,9 +86,7 @@ class _RougailConfig:
) )
if self.root: if self.root:
rougailconfig.config.value.importation(self.config.value.exportation()) rougailconfig.config.value.importation(self.config.value.exportation())
rougailconfig.config.property.importation( rougailconfig.config.property.importation(self.config.property.exportation())
self.config.property.exportation()
)
rougailconfig.config.property.read_only() rougailconfig.config.property.read_only()
rougailconfig.root = self.root rougailconfig.root = self.root
rougailconfig.config = self.config rougailconfig.config = self.config
@ -100,9 +99,7 @@ class _RougailConfig:
return rougailconfig return rougailconfig
def generate_config(self): def generate_config(self):
root, extra_vars = _rougail_config( root, extra_vars = _rougail_config(self.backward_compatibility, self.add_extra_options)
self.backward_compatibility, self.add_extra_options
)
self.root = root self.root = root
self.config = Config( self.config = Config(
self.root, self.root,
@ -346,13 +343,6 @@ load_unexist_redefine:
commandline: false commandline: false
default: False default: False
secret_manager:
pattern:
description: {_("The secret pattern to build item name in Bitwarden")}
help: {_("The pattern is in Jinja format")}
default: "{{{{ project }}}} - {{{{ environment }}}} - {{{{ service }}}} - {{{{ user }}}}"
""" """
processes = { processes = {
"structural": [], "structural": [],
@ -377,22 +367,14 @@ secret_manager:
{NAME}: {NAME}:
description: Select for {NAME} description: Select for {NAME}
""".format(
NAME=normalize_family(process),
)
if process != "structural":
rougail_process += """
alternative_name: {NAME[0]}
""".format(
NAME=normalize_family(process),
)
rougail_process += """
choices: choices:
""" """.format(
NAME=normalize_family(process),
)
for obj in objects: for obj in objects:
rougail_process += f" - {obj['name']}\n" rougail_process += f" - {obj['name']}\n"
if process == "structural": if process == "structural":
# rougail_process += """ commandline: false # rougail_process += """ commandline: false
rougail_process += """ multi: true rougail_process += """ multi: true
default: default:
- directory - directory
@ -409,10 +391,10 @@ secret_manager:
jinja: | jinja: |
""" """
for hidden_output in hidden_outputs: for hidden_output in hidden_outputs:
rougail_process += """ {% if _.output is not propertyerror and _.output == 'NAME' %} rougail_process += """ {% if _.output == 'NAME' %}
Cannot load structural for NAME output Cannot load structural for NAME output
{% endif %} {% endif %}""".replace(
""".replace("NAME", hidden_output "NAME", hidden_output
) )
elif process == "user data": elif process == "user data":
rougail_process += """ multi: true rougail_process += """ multi: true
@ -429,7 +411,7 @@ secret_manager:
jinja: | jinja: |
""" """
for hidden_output in hidden_outputs: for hidden_output in hidden_outputs:
rougail_process += """ {% if _.output is not propertyerror and _.output == 'NAME' %} rougail_process += """ {% if _.output == 'NAME' %}
Cannot load user data for NAME output Cannot load user data for NAME output
{% endif %}""".replace( {% endif %}""".replace(
"NAME", hidden_output "NAME", hidden_output
@ -473,7 +455,10 @@ default_params:
mandatory: false mandatory: false
default: {value} default: {value}
""" """
for process_empty in processes_empty:
rougail_process += process_empty
rougail_options += rougail_process rougail_options += rougail_process
# print(rougail_options)
convert = FakeRougailConvert(add_extra_options) convert = FakeRougailConvert(add_extra_options)
convert.init() convert.init()
convert.namespace = None convert.namespace = None
@ -483,13 +468,6 @@ default_params:
"1.1", "1.1",
YAML().load(rougail_options), YAML().load(rougail_options),
) )
for process_empty in processes_empty:
convert.parse_root_file(
"rougail.config",
"",
"1.1",
YAML().load(process_empty),
)
extra_vars = {} extra_vars = {}
objects = [] objects = []
for obj in sorted( for obj in sorted(

View file

@ -179,16 +179,12 @@ class ParserVariable:
] ]
self.structurals = rougailconfig["step.structural"] self.structurals = rougailconfig["step.structural"]
self.user_datas = rougailconfig["step.user_data"] self.user_datas = rougailconfig["step.user_data"]
try:
self.output = rougailconfig["step.output"] self.output = rougailconfig["step.output"]
except:
self.output = None
self.tiramisu_cache = rougailconfig["tiramisu_cache"] self.tiramisu_cache = rougailconfig["tiramisu_cache"]
self.load_unexist_redefine = rougailconfig["load_unexist_redefine"] self.load_unexist_redefine = rougailconfig["load_unexist_redefine"]
self.secret_pattern = rougailconfig['secret_manager.pattern']
# change default initkwargs in CONVERT_OPTION # change default initkwargs in CONVERT_OPTION
if hasattr(rougailconfig, "config"): if hasattr(rougailconfig, 'config'):
for sub_od in rougailconfig.config.option("default_params"): for sub_od in rougailconfig.config.option('default_params'):
for option in sub_od: for option in sub_od:
if option.owner.isdefault(): if option.owner.isdefault():
continue continue
@ -220,7 +216,9 @@ class ParserVariable:
family = type( family = type(
family.__name__ + "_" + structural, (family, module.Family), {} family.__name__ + "_" + structural, (family, module.Family), {}
) )
if not self.walker and "Walker" in module.__all__: if "Walker" in module.__all__:
if self.walker:
raise Exception("multiple walker defined!")
self.walker = module.Walker self.walker = module.Walker
self.variable = variable self.variable = variable
self.family = family self.family = family
@ -395,7 +393,7 @@ class ParserVariable:
exists = obj.pop("exists", None) exists = obj.pop("exists", None)
else: else:
exists = None exists = None
force_to_attrs = list(self.list_attributes(obj, filename)) force_to_attrs = list(self.list_attributes(obj))
for key, value in obj.items(): for key, value in obj.items():
if key in force_to_attrs: if key in force_to_attrs:
if key.startswith("_"): if key.startswith("_"):
@ -408,9 +406,7 @@ class ParserVariable:
if family_obj: if family_obj:
if exists in [None, True] and not obj.pop("redefine", False): if exists in [None, True] and not obj.pop("redefine", False):
msg = _('family "{0}" define multiple time').format(path) msg = _('family "{0}" define multiple time').format(path)
raise DictConsistencyError( raise DictConsistencyError(msg, 32, self.paths[path].xmlfiles + [filename])
msg, 32, self.paths[path].xmlfiles + [filename]
)
# convert to Calculation objects # convert to Calculation objects
self.parse_parameters( self.parse_parameters(
path, path,
@ -503,17 +499,10 @@ class ParserVariable:
def list_attributes( def list_attributes(
self, self,
obj: Dict[str, Any], obj: Dict[str, Any],
filename: str,
) -> Iterator[str]: ) -> Iterator[str]:
"""List attributes""" """List attributes"""
force_to_variable = [] force_to_variable = []
for key, value in obj.items(): for key, value in obj.items():
if not isinstance(key, str):
raise DictConsistencyError(
f'a key is not in string format: {key}',
103,
[filename],
)
if key in force_to_variable: if key in force_to_variable:
continue continue
if key.startswith("_"): if key.startswith("_"):
@ -667,17 +656,13 @@ class ParserVariable:
version, version,
) )
self.parse_params(path, obj, filename) self.parse_params(path, obj, filename)
self.parse_secret_manager(path, obj, filename, version, family_is_dynamic)
exists = obj.pop("exists", None) exists = obj.pop("exists", None)
if path in self.paths: if path in self.paths:
if not self.load_unexist_redefine: if not self.load_unexist_redefine and exists is False:
if exists is False:
return return
if not obj.pop("redefine", False): if not obj.pop("redefine", False):
msg = _('variable "{0}" define multiple time').format(path) msg = _('variable "{0}" define multiple time').format(path)
raise DictConsistencyError( raise DictConsistencyError(msg, 45, self.paths[path].xmlfiles + [filename])
msg, 45, self.paths[path].xmlfiles + [filename]
)
self.paths.add( self.paths.add(
path, path,
self.paths[path].model_copy(update=obj), self.paths[path].model_copy(update=obj),
@ -779,8 +764,7 @@ class ParserVariable:
if "params" not in obj: if "params" not in obj:
return return
if not isinstance(obj["params"], dict): if not isinstance(obj["params"], dict):
raise DictConsistencyError( raise DictConsistencyError(_("params must be a dict for {0}").format(path),
_("params must be a dict for {0}").format(path),
55, 55,
[filename], [filename],
) )
@ -796,45 +780,17 @@ class ParserVariable:
is_follower=None, is_follower=None,
attribute=None, attribute=None,
family_is_dynamic=None, family_is_dynamic=None,
namespace=self.namespace,
xmlfiles=[filename], xmlfiles=[filename],
) )
) )
except ValidationError as err: except ValidationError as err:
raise DictConsistencyError( raise DictConsistencyError(
_('"{0}" has an invalid "params" for {1}: {2}').format( _('"{0}" has an invalid "params" for {1}: {2}').format(key, path, err),
key, path, err
),
54, 54,
[filename], [filename],
) from err ) from err
obj["params"] = params obj["params"] = params
def parse_secret_manager(self, path, obj, filename, version, family_is_dynamic):
"""Parse variable secret_manager"""
if "secret_manager" not in obj:
return
if not isinstance(obj["secret_manager"], dict):
raise DictConsistencyError(
_("secret_manager must be a dict for {0}").format(path),
64,
[filename],
)
secret_manager = {"type": "jinja",
"jinja": self.secret_pattern,
"params": obj["secret_manager"],
}
self.set_calculation(
obj,
"secret_manager",
secret_manager,
path,
family_is_dynamic,
False,
version,
[filename],
)
def add_variable( def add_variable(
self, self,
name: str, name: str,
@ -922,9 +878,6 @@ class ParserVariable:
calculations = calculations[1] calculations = calculations[1]
if not isinstance(value, dict) or attribute not in calculations: if not isinstance(value, dict) or attribute not in calculations:
return False return False
return self.check_auto_type(value)
def check_auto_type(self, value):
if "type" in value: if "type" in value:
return value["type"] in CALCULATION_TYPES return value["type"] in CALCULATION_TYPES
# auto set type # auto set type
@ -990,7 +943,6 @@ class ParserVariable:
val["family_is_dynamic"] = family_is_dynamic val["family_is_dynamic"] = family_is_dynamic
val["is_follower"] = is_follower val["is_follower"] = is_follower
val["attribute"] = attribute val["attribute"] = attribute
val["namespace"] = self.namespace
val["xmlfiles"] = xmlfiles val["xmlfiles"] = xmlfiles
if param_typ not in PARAM_TYPES: if param_typ not in PARAM_TYPES:
raise DictConsistencyError( raise DictConsistencyError(
@ -1016,7 +968,7 @@ class ParserVariable:
) )
# #
if typ == "identifier" and not family_is_dynamic: if typ == "identifier" and not family_is_dynamic:
msg = f'identifier calculation for "{attribute}" in "{path}" cannot be set variable is not in dynamic family' msg = f'identifier calculation for "{attribute}" in "{path}" cannot be set none dynamic family'
raise DictConsistencyError(msg, 53, xmlfiles) raise DictConsistencyError(msg, 53, xmlfiles)
if attribute in PROPERTY_ATTRIBUTE: if attribute in PROPERTY_ATTRIBUTE:
calc = CALCULATION_PROPERTY_TYPES[typ](**calculation_object) calc = CALCULATION_PROPERTY_TYPES[typ](**calculation_object)
@ -1154,9 +1106,7 @@ class RougailConvert(ParserVariable):
def parse_directories(self) -> None: def parse_directories(self) -> None:
if not self.walker: if not self.walker:
msg = _( msg = _('invalid "structural" definition ({0}), we cannot load any structural file!').format(self.structurals)
'invalid "structural" definition ({0}), we cannot load any structural file!'
).format(self.structurals)
raise DictConsistencyError(msg, 51, None) raise DictConsistencyError(msg, 51, None)
self.init() self.init()
self.walker(self) self.walker(self)

View file

@ -113,23 +113,23 @@ def get_convert_option_types():
if obj == tiramisu.SymLinkOption: if obj == tiramisu.SymLinkOption:
continue continue
if obj == tiramisu.ChoiceOption: if obj == tiramisu.ChoiceOption:
inst = obj("a", "a", ("a",), **initkwargs) inst = obj('a', 'a', ('a',), **initkwargs)
else: else:
inst = obj("a", "a", **initkwargs) inst = obj('a', 'a', **initkwargs)
extra = getattr(inst, "_extra", {}) extra = getattr(inst, '_extra', {})
if not extra: if not extra:
continue continue
params = [] params = []
for key, value in extra.items(): for key, value in extra.items():
if key.startswith("_"): if key.startswith('_'):
continue continue
multi = False multi = False
if isinstance(value, bool): if isinstance(value, bool):
key_type = "boolean" key_type = 'boolean'
elif isinstance(value, str): elif isinstance(value, str):
key_type = "string" key_type = 'string'
elif isinstance(value, list): elif isinstance(value, list):
key_type = "string" key_type = 'string'
multi = True multi = True
params.append((key, key_type, multi, value)) params.append((key, key_type, multi, value))
yield typ, params yield typ, params
@ -137,7 +137,6 @@ def get_convert_option_types():
class Param(BaseModel): class Param(BaseModel):
key: str key: str
namespace: Optional[str]
model_config = ConfigDict(extra="forbid") model_config = ConfigDict(extra="forbid")
def __init__( def __init__(
@ -192,24 +191,19 @@ class IndexParam(Param):
self, self,
**kwargs, **kwargs,
) -> None: ) -> None:
if not kwargs["is_follower"]: if not kwargs["is_follower"]:
msg = f'the variable "{kwargs["path"]}" is not a follower, so cannot have index type for param in "{kwargs["attribute"]}"' msg = f'the variable "{kwargs["path"]}" is not a follower, so cannot have index type for param in "{kwargs["attribute"]}"'
raise DictConsistencyError(msg, 25, kwargs["xmlfiles"]) raise DictConsistencyError(msg, 25, kwargs["xmlfiles"])
super().__init__(**kwargs) super().__init__(**kwargs)
class NamespaceParam(Param):
type: str
namespace: str
PARAM_TYPES = { PARAM_TYPES = {
"any": AnyParam, "any": AnyParam,
"variable": VariableParam, "variable": VariableParam,
"identifier": IdentifierParam, "identifier": IdentifierParam,
"information": InformationParam, "information": InformationParam,
"index": IndexParam, "index": IndexParam,
"namespace": NamespaceParam,
} }
@ -244,7 +238,7 @@ class Calculation(BaseModel):
) )
if not variable: if not variable:
if not param.get("optional"): if not param.get("optional"):
msg = f'cannot find variable "{param["variable"]}" defined in attribute "{self.attribute_name}" for "{self.path}"' msg = f'cannot find variable "{param["variable"]}" defined attribute in "{self.attribute_name}" for "{self.path}"'
raise DictConsistencyError(msg, 22, self.xmlfiles) raise DictConsistencyError(msg, 22, self.xmlfiles)
continue continue
if not isinstance(variable, objectspace.variable): if not isinstance(variable, objectspace.variable):
@ -294,7 +288,6 @@ class JinjaCalculation(Calculation):
"validators", "validators",
"choices", "choices",
"dynamic", "dynamic",
"secret_manager",
] ]
jinja: StrictStr jinja: StrictStr
params: Optional[List[Param]] = None params: Optional[List[Param]] = None
@ -373,7 +366,7 @@ class JinjaCalculation(Calculation):
self, self,
objectspace, objectspace,
) -> dict: ) -> dict:
if self.attribute_name in ["default", "secret_manager"]: if self.attribute_name == "default":
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[self.path]
@ -481,8 +474,7 @@ class _VariableCalculation(Calculation):
"variable": variable, "variable": variable,
"propertyerror": self.propertyerror, "propertyerror": self.propertyerror,
} }
is_variable_calculation = isinstance(self, VariableCalculation) if isinstance(self, VariableCalculation) and self.optional:
if is_variable_calculation and self.optional:
param["optional"] = self.optional param["optional"] = self.optional
if identifier: if identifier:
param["identifier"] = identifier param["identifier"] = identifier
@ -528,7 +520,6 @@ class _VariableCalculation(Calculation):
variable.multi variable.multi
or variable.path.rsplit(".", 1)[0] != self.path.rsplit(".", 1)[0] or variable.path.rsplit(".", 1)[0] != self.path.rsplit(".", 1)[0]
): ):
if is_variable_calculation:
# it's not a follower or not in same leadership # it's not a follower or not in same leadership
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is a multi' msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is a multi'
raise DictConsistencyError(msg, 21, self.xmlfiles) raise DictConsistencyError(msg, 21, self.xmlfiles)
@ -606,9 +597,6 @@ class VariablePropertyCalculation(_VariableCalculation):
raise DictConsistencyError(msg, 104, variable.xmlfiles) raise DictConsistencyError(msg, 104, variable.xmlfiles)
when = self.when_not when = self.when_not
inverse = True inverse = True
else:
if variable.multi:
when = []
else: else:
if variable.type != "boolean": if variable.type != "boolean":
raise Exception("only boolean!") raise Exception("only boolean!")
@ -749,31 +737,13 @@ class IndexCalculation(Calculation):
} }
class NamespaceCalculation(Calculation):
attribute_name: Literal["default", "secret_manager"]
def to_function(
self,
objectspace,
) -> dict:
namespace = objectspace.namespace
if namespace:
namespace = objectspace.paths[namespace].description
return {
"function": "calc_value",
"params": {None: [namespace]},
}
CALCULATION_TYPES = { CALCULATION_TYPES = {
"jinja": JinjaCalculation, "jinja": JinjaCalculation,
"information": InformationCalculation, "information": InformationCalculation,
"variable": VariableCalculation, "variable": VariableCalculation,
"identifier": IdentifierCalculation, "identifier": IdentifierCalculation,
# FOR VERSION 1.0
"suffix": IdentifierCalculation, "suffix": IdentifierCalculation,
"index": IndexCalculation, "index": IndexCalculation,
"namespace": NamespaceCalculation,
} }
CALCULATION_PROPERTY_TYPES = { CALCULATION_PROPERTY_TYPES = {
"jinja": JinjaCalculation, "jinja": JinjaCalculation,
@ -783,7 +753,6 @@ CALCULATION_PROPERTY_TYPES = {
"index": IndexCalculation, "index": IndexCalculation,
} }
BASETYPE_CALC = Union[StrictBool, StrictInt, StrictFloat, StrictStr, Calculation, None] BASETYPE_CALC = Union[StrictBool, StrictInt, StrictFloat, StrictStr, Calculation, None]
SECRET_BASETYPE_CALC = Union[StrictStr, JinjaCalculation]
class Family(BaseModel): class Family(BaseModel):
@ -830,7 +799,6 @@ class Variable(BaseModel):
validators: Optional[List[Calculation]] = None validators: Optional[List[Calculation]] = None
# value # value
default: Union[List[BASETYPE_CALC], BASETYPE_CALC] = None default: Union[List[BASETYPE_CALC], BASETYPE_CALC] = None
secret_manager: Optional[JinjaCalculation] = None
# properties # properties
auto_save: bool = False auto_save: bool = False
mandatory: Union[None, bool, Calculation] = None mandatory: Union[None, bool, Calculation] = None

View file

@ -86,10 +86,8 @@ def test_propertyerror(value: Any) -> bool:
ENV.tests["propertyerror"] = test_propertyerror ENV.tests["propertyerror"] = test_propertyerror
def load_functions(path, dict_func=None): def load_functions(path):
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
if dict_func is None:
dict_func = func
loader = _SourceFileLoader("func", path) loader = _SourceFileLoader("func", path)
spec = _spec_from_loader(loader.name, loader) spec = _spec_from_loader(loader.name, loader)
func_ = _module_from_spec(spec) func_ = _module_from_spec(spec)
@ -97,7 +95,7 @@ def load_functions(path, dict_func=None):
for function in dir(func_): for function in dir(func_):
if function.startswith("_"): if function.startswith("_"):
continue continue
dict_func[function] = getattr(func_, function) func[function] = getattr(func_, function)
def rougail_calc_value(*args, __default_value=None, __internal_multi=False, **kwargs): def rougail_calc_value(*args, __default_value=None, __internal_multi=False, **kwargs):
@ -109,21 +107,6 @@ def rougail_calc_value(*args, __default_value=None, __internal_multi=False, **kw
return values return values
def kw_to_string(kw, root=None):
# {'_': {'interfaces': {'ip': ['192.168.44.19', '192.168.44.12'], 'domain_name': ['nginx-reverse-proxy.reverseproxy.test.net', 'nginx-reverse-proxy.localdns.test.net']}, 'dns_client_address': 'nginx-reverse-proxy.localdns.test.net'}}
for name, data in kw.items():
if root is None:
path = name
else:
path = root + '.' + name
if isinstance(data, dict):
yield from kw_to_string(data, root=path)
else:
yield f"{path}={data}"
pass
@function_waiting_for_error @function_waiting_for_error
def jinja_to_function( def jinja_to_function(
__internal_variable, __internal_variable,
@ -161,13 +144,12 @@ def jinja_to_function(
try: try:
values = ENV.get_template(__internal_jinja).render(kw, **func).strip() values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
except Exception as err: except Exception as err:
kw_str = ", ".join(kw_to_string(kw))
raise ConfigError( raise ConfigError(
f'cannot calculating "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)} with parameters "{kw_str}": {err}' f'cannot calculating "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}'
) from err ) from err
convert = CONVERT_OPTION[__internal_type].get("func", str) convert = CONVERT_OPTION[__internal_type].get("func", str)
if __internal_multi: if __internal_multi:
values = [convert(val.strip()) for val in values.split("\n") if val.strip() != ""] values = [convert(val) for val in values.split("\n") if val != ""]
if not values and __default_value is not None: if not values and __default_value is not None:
return __default_value return __default_value
return values return values
@ -222,7 +204,6 @@ func["jinja_to_property"] = jinja_to_property
func["jinja_to_property_help"] = jinja_to_property_help func["jinja_to_property_help"] = jinja_to_property_help
func["variable_to_property"] = variable_to_property func["variable_to_property"] = variable_to_property
func["valid_with_jinja"] = valid_with_jinja func["valid_with_jinja"] = valid_with_jinja
func["normalize_family"] = normalize_family
class ConvertDynOptionDescription(DynOptionDescription): class ConvertDynOptionDescription(DynOptionDescription):

View file

@ -350,11 +350,6 @@ class Common:
else: else:
value = str(param["value"]) value = str(param["value"])
return "ParamValue(" + value + ")" return "ParamValue(" + value + ")"
if param["type"] == "namespace":
namespace = param["namespace"]
if namespace:
namespace = self.objectspace.paths[param["namespace"]].description
return f"ParamValue('{namespace}')"
raise Exception("pfff") raise Exception("pfff")
def build_option_param( def build_option_param(

View file

@ -23,12 +23,7 @@ from typing import List
from re import findall from re import findall
from tiramisu import undefined, Calculation from tiramisu import undefined, Calculation
from tiramisu.error import ( from tiramisu.error import PropertiesOptionError, LeadershipError, ConfigError, CancelParam
PropertiesOptionError,
LeadershipError,
ConfigError,
CancelParam,
)
from .i18n import _ from .i18n import _
from .object_model import CONVERT_OPTION from .object_model import CONVERT_OPTION
@ -156,15 +151,8 @@ class UserDatas:
if path not in self.values: if path not in self.values:
continue continue
options = self.values[path].get("options", {}) options = self.values[path].get("options", {})
if ( if options.get('allow_secrets_variables', True) is False and option.type() == 'password':
options.get("allow_secrets_variables", True) is False self.errors.append(_('the variable "{0}" contains secrets and should not be defined in {1}').format(path, self.values[path]["source"]))
and option.type() == "password"
):
self.errors.append(
_(
'the variable "{0}" contains secrets and should not be defined in {1}'
).format(path, self.values[path]["source"])
)
continue continue
value = self.values[path]["values"] value = self.values[path]["values"]
needs_convert = options.get("needs_convert", False) needs_convert = options.get("needs_convert", False)
@ -224,9 +212,7 @@ class UserDatas:
option = self.config.option(path) option = self.config.option(path)
if option.isoptiondescription(): if option.isoptiondescription():
self.errors.warnings( self.errors.warnings(
_('the option "{0}" is an option description').format( _('the option "{0}" is an option description').format(option.path())
option.path()
)
) )
continue continue
value = data["values"] value = data["values"]

View file

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

View file

@ -1,3 +0,0 @@
{
"rougail.variable": "Rougail"
}

View file

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

View file

@ -1,15 +0,0 @@
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 = StrOption(name="variable", doc="a variable", default=Calculation(func['calc_value'], Params((ParamValue("Rougail")))), properties=frozenset({"standard"}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

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

View file

@ -1,3 +0,0 @@
{
"rougail.variable": "Rougail"
}

View file

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

View file

@ -1,16 +0,0 @@
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['default_rougail.variable'] = "{{ namespace }}"
option_2 = StrOption(name="variable", doc="a variable", default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.variable"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/00_8calculation_param_namespace/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.variable"), 'namespace': ParamValue('Rougail')})), properties=frozenset({"standard"}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,6 +0,0 @@
{
"rougail.condition": {
"owner": "default",
"value": []
}
}

View file

@ -1,3 +0,0 @@
{
"rougail.condition": []
}

View file

@ -1,6 +0,0 @@
{
"rougail.condition": {
"owner": "default",
"value": []
}
}

View file

@ -1,16 +0,0 @@
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 = StrOption(name="condition", doc="a condition", multi=True, properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
option_3 = StrOption(name="variable", doc="a variable", multi=True, properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'__internal_multi': ParamValue(True), 'when': ParamValue([]), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3], properties=frozenset({"basic"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,11 +0,0 @@
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 = StrOption(name="condition", doc="a condition", multi=True, properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
option_2 = StrOption(name="variable", doc="a variable", multi=True, properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_1)), kwargs={'__internal_multi': ParamValue(True), 'when': ParamValue([]), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'string'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2])

View file

@ -1,13 +0,0 @@
{
"rougail.condition": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.variable": {
"owner": "default",
"value": []
}
}

View file

@ -1,7 +0,0 @@
{
"rougail.condition": [
"val1",
"val2"
],
"rougail.variable": []
}

View file

@ -1,13 +0,0 @@
{
"rougail.condition": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.variable": {
"owner": "default",
"value": []
}
}

View file

@ -1,16 +0,0 @@
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 = StrOption(name="condition", doc="a condition", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_3 = StrOption(name="variable", doc="a variable", multi=True, properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'__internal_multi': ParamValue(True), 'when': ParamValue([]), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3], properties=frozenset({"basic"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,11 +0,0 @@
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 = StrOption(name="condition", doc="a condition", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_2 = StrOption(name="variable", doc="a variable", multi=True, properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_1)), kwargs={'__internal_multi': ParamValue(True), 'when': ParamValue([]), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'string'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2])

View file

@ -1,25 +0,0 @@
{
"rougail.var": {
"owner": "default",
"value": [
"val.1",
"val.2"
]
},
"rougail.dynval_1.var1": {
"owner": "default",
"value": "val.1"
},
"rougail.dynval_1.var2": {
"owner": "default",
"value": "val.1"
},
"rougail.dynval_2.var1": {
"owner": "default",
"value": "val.2"
},
"rougail.dynval_2.var2": {
"owner": "default",
"value": "val.2"
}
}

View file

@ -1,10 +0,0 @@
{
"rougail.var": [
"val.1",
"val.2"
],
"rougail.dynval_1.var1": "val.1",
"rougail.dynval_1.var2": "val.1",
"rougail.dynval_2.var1": "val.2",
"rougail.dynval_2.var2": "val.2"
}

View file

@ -1,25 +0,0 @@
{
"rougail.var": {
"owner": "default",
"value": [
"val.1",
"val.2"
]
},
"rougail.dynval_1.var1": {
"owner": "default",
"value": "val.1"
},
"rougail.dynval_1.var2": {
"owner": "default",
"value": "val.1"
},
"rougail.dynval_2.var1": {
"owner": "default",
"value": "val.2"
},
"rougail.dynval_2.var2": {
"owner": "default",
"value": "val.2"
}
}

View file

@ -1,19 +0,0 @@
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['default_rougail.dyn{{ identifier }}.var2'] = "{{ identifier }}"
option_2 = StrOption(name="var", doc="A suffix variable", multi=True, default=["val.1", "val.2"], default_multi="val.1", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_4 = StrOption(name="var1", doc="A dynamic variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_5 = StrOption(name="var2", doc="A dynamic variable", default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.dyn{{ identifier }}.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/60_0family_dynamic_forbidden_char/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.dyn{{ identifier }}.var2"), 'identifier': ParamIdentifier()})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
optiondescription_3 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic family", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_2)))), children=[option_4, option_5], properties=frozenset({"standard"}), informations={'dynamic_variable': 'rougail.var'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, optiondescription_3], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,14 +0,0 @@
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['default_dyn{{ identifier }}.var2'] = "{{ identifier }}"
option_1 = StrOption(name="var", doc="A suffix variable", multi=True, default=["val.1", "val.2"], default_multi="val.1", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_3 = StrOption(name="var1", doc="A dynamic variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_4 = StrOption(name="var2", doc="A dynamic variable", default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_dyn{{ identifier }}.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/60_0family_dynamic_forbidden_char/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("dyn{{ identifier }}.var2"), 'identifier': ParamIdentifier()})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
optiondescription_2 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="A dynamic family", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_1)))), children=[option_3, option_4], properties=frozenset({"standard"}), informations={'dynamic_variable': 'var'})
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, optiondescription_2])

View file

@ -1,10 +0,0 @@
{
"rougail.var1": {
"owner": "default",
"value": []
},
"rougail.var2": {
"owner": "default",
"value": null
}
}

View file

@ -1,4 +0,0 @@
{
"rougail.var1": [],
"rougail.var2": null
}

View file

@ -1,10 +0,0 @@
{
"rougail.var1": {
"owner": "default",
"value": []
},
"rougail.var2": {
"owner": "default",
"value": null
}
}

View file

@ -1,18 +0,0 @@
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 = StrOption(name="var1", doc="A suffix variable", multi=True, properties=frozenset({"standard"}), informations={'type': 'string', 'test': ('val1',)})
option_4 = StrOption(name="var", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
optiondescription_3 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="dyn{{ identifier }}", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_2)))), children=[option_4], properties=frozenset({"basic"}), informations={'dynamic_variable': 'rougail.var1'})
option_5 = StrOption(name="var2", doc="A variable calculated", default=Calculation(func['calc_value'], Params((ParamDynOption(option_4, ["val1"], optional=True)))), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, optiondescription_3, option_5], properties=frozenset({"basic"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,10 +0,0 @@
{
"rougail.var2": {
"owner": "default",
"value": null
},
"rougail.var1": {
"owner": "default",
"value": []
}
}

View file

@ -1,4 +0,0 @@
{
"rougail.var2": null,
"rougail.var1": []
}

View file

@ -1,10 +0,0 @@
{
"rougail.var2": {
"owner": "default",
"value": null
},
"rougail.var1": {
"owner": "default",
"value": []
}
}

View file

@ -1,18 +0,0 @@
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_5 = StrOption(name="var", doc="A dynamic variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
option_2 = StrOption(name="var2", doc="A variable calculated", default=Calculation(func['calc_value'], Params((ParamDynOption(option_5, ["val1"], optional=True)))), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_3 = StrOption(name="var1", doc="A suffix variable", multi=True, properties=frozenset({"standard"}), informations={'type': 'string', 'test': ('val1', 'val2')})
optiondescription_4 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="dyn{{ identifier }}", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_3)))), children=[option_5], properties=frozenset({"basic"}), informations={'dynamic_variable': 'rougail.var1'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3, optiondescription_4], properties=frozenset({"basic"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -1,24 +0,0 @@
{
"rougail.var": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.my_dyn_family_val1.var": {
"owner": "default",
"value": "val1"
},
"rougail.my_dyn_family_val2.var": {
"owner": "default",
"value": "val2"
},
"rougail.var2": {
"owner": "default",
"value": [
"val1",
"val2"
]
}
}

View file

@ -1,12 +0,0 @@
{
"rougail.var": [
"val1",
"val2"
],
"rougail.my_dyn_family_val1.var": "val1",
"rougail.my_dyn_family_val2.var": "val2",
"rougail.var2": [
"val1",
"val2"
]
}

View file

@ -1,24 +0,0 @@
{
"rougail.var": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.my_dyn_family_val1.var": {
"owner": "default",
"value": "val1"
},
"rougail.my_dyn_family_val2.var": {
"owner": "default",
"value": "val2"
},
"rougail.var2": {
"owner": "default",
"value": [
"val1",
"val2"
]
}
}

View file

@ -1,18 +0,0 @@
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 = StrOption(name="var", doc="a suffix variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
option_4 = StrOption(name="var", doc="a variable inside a dynamic family", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"standard"}), informations={'type': 'string'})
optiondescription_3 = ConvertDynOptionDescription(name="my_dyn_family_{{ identifier }}", doc="a dynamic family", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_2, notraisepropertyerror=True)), kwargs={'allow_none': ParamValue(True)})), children=[option_4], properties=frozenset({"standard"}), informations={'dynamic_variable': 'rougail.var'})
option_5 = StrOption(name="var2", doc="a variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_4)), kwargs={'__internal_multi': ParamValue(True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, optiondescription_3, option_5], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -45,7 +45,7 @@ excludes = set([
]) ])
test_ok -= excludes test_ok -= excludes
test_raise -= excludes test_raise -= excludes
# test_ok = ['00_8calculation_param_namespace'] # test_ok = ['00_9default_calculation_multi_optional']
#test_ok = [] #test_ok = []
#test_raise = ['88valid_enum_invalid_default'] #test_raise = ['88valid_enum_invalid_default']
#test_raise = [] #test_raise = []