diff --git a/src/rougail/annotator.py b/src/rougail/annotator.py
index 7e2bfacc..a38a94f2 100644
--- a/src/rougail/annotator.py
+++ b/src/rougail/annotator.py
@@ -237,6 +237,7 @@ class ServiceAnnotator:
self.paths.add_variable('services',
path,
'service',
+ False,
variable,
)
return variable
@@ -1116,7 +1117,11 @@ class SpaceAnnotator(object):
# if param.optional is True:
# param_option_indexes.append(fill_idx)
try:
- param.text = self.paths.get_variable_path(param.text, namespace)
+ param.text, suffix = self.paths.get_variable_path(param.text,
+ namespace,
+ with_suffix=True)
+ if suffix:
+ param.suffix = suffix
except CreoleDictConsistencyError as err:
if param.optional is True:
param_option_indexes.append(fill_idx)
diff --git a/src/rougail/loader.py b/src/rougail/loader.py
index b6637b2f..097a4360 100644
--- a/src/rougail/loader.py
+++ b/src/rougail/loader.py
@@ -11,7 +11,7 @@ from tiramisu import (StrOption, OptionDescription, DynOptionDescription, PortOp
NetworkOption, NetmaskOption, DomainnameOption, BroadcastOption,
URLOption, EmailOption, FilenameOption, UsernameOption, DateOption,
PasswordOption, BoolOption, MACOption, Leadership, submulti,
- Params, ParamSelfOption, ParamOption, ParamValue, Calculation, calc_value,
+ Params, ParamSelfOption, ParamOption, ParamDynOption, ParamValue, Calculation, calc_value,
groups, owners)
from tiramisu.error import ConfigError
@@ -431,7 +431,7 @@ class Variable(Common):
transitive = False
else:
raise CreoleLoaderError(_('unknown transitive boolean {}').format(transitive))
- value = [param.text, transitive]
+ value = [param.text, transitive, param.attrib.get('suffix')]
elif param.attrib['type'] == 'number':
value = int(param.text)
else:
@@ -462,10 +462,21 @@ class Variable(Common):
if len(value) == 3:
for param in value[1]:
if isinstance(param[1], list):
+ option = self.storage.get(param[1][0]).get()
+ param_kwargs = {'notraisepropertyerror': param[1][1]}
if value[0] in FUNC_TO_DICT:
- param_value = ParamOption(self.storage.get(param[1][0]).get(), notraisepropertyerror=param[1][1], todict=True)
+ param_kwargs['todict'] = True
+ if not param[1][2]:
+ param_value = ParamOption(option,
+ **param_kwargs,
+ )
else:
- param_value = ParamOption(self.storage.get(param[1][0]).get(), notraisepropertyerror=param[1][1])
+ family = '.'.join(param[1][0].split('.', 3)[:2])
+ param_value = ParamDynOption(option,
+ param[1][2],
+ self.storage.get(family).get(),
+ **param_kwargs,
+ )
else:
param_value = ParamValue(param[1])
if not param[0]:
diff --git a/src/rougail/objspace.py b/src/rougail/objspace.py
index 306be9fd..284ec2a7 100644
--- a/src/rougail/objspace.py
+++ b/src/rougail/objspace.py
@@ -197,6 +197,7 @@ class CreoleObjSpace(object):
self.paths.add_variable(namespace,
name,
family.name,
+ False,
variable_obj,
)
return variable_obj
@@ -423,7 +424,13 @@ class CreoleObjSpace(object):
if list(child) != []:
self.xml_parse_document(child, creoleobj, namespace, is_in_family)
- def _fill_creoleobj_path_attribute(self, space, child, namespace, document, creoleobj): # pylint: disable=R0913
+ def _fill_creoleobj_path_attribute(self,
+ space,
+ child,
+ namespace,
+ document,
+ creoleobj,
+ ): # pylint: disable=R0913
"""Fill self.paths attributes
"""
if not isinstance(space, self.help): # pylint: disable=E1101
@@ -432,6 +439,7 @@ class CreoleObjSpace(object):
self.paths.add_variable(namespace,
child.attrib['name'],
family_name,
+ document.attrib.get('dynamic') != None,
creoleobj)
if child.attrib.get('redefine', 'False') == 'True':
if namespace == 'creole':
@@ -655,8 +663,10 @@ class Path:
new_path = namespace + '.' + leader_family_name + '.' + leader_name + '.' + name
self.add_variable(namespace,
new_path,
- family=dico['family'],
- creoleobj=dico['creoleobj'])
+ dico['family'],
+ False,
+ dico['creoleobj'],
+ )
name = new_path
dico = self._get_variable(name)
if dico['leader'] != None:
@@ -671,8 +681,9 @@ class Path:
def add_variable(self,
namespace: str,
name: str,
- family: str=None,
- creoleobj=None,
+ family: str,
+ is_dynamic: bool,
+ creoleobj,
) -> str: # pylint: disable=C0111
if namespace == 'creole' or '.' in name:
varname = name
@@ -682,6 +693,7 @@ class Path:
family=family,
namespace=namespace,
leader=None,
+ is_dynamic=is_dynamic,
creoleobj=creoleobj)
def get_variable_name(self,
@@ -717,22 +729,32 @@ class Path:
name: str,
current_namespace: str,
allow_source: str=False,
+ with_suffix: bool=False,
) -> str: # pylint: disable=C0111
if current_namespace is None: # pragma: no cover
raise CreoleOperationError('current_namespace must not be None')
- dico = self._get_variable(name)
+ if with_suffix:
+ dico, suffix = self._get_variable(name,
+ with_suffix=True,
+ )
+ else:
+ dico = self._get_variable(name)
if not allow_source:
if dico['namespace'] not in ['creole', 'services'] and current_namespace != dico['namespace']:
raise CreoleDictConsistencyError(_('A variable located in the {} namespace '
'shall not be used in the {} namespace').format(
dico['namespace'], current_namespace))
if '.' in dico['name']:
- return dico['name']
- list_path = [dico['namespace'], dico['family']]
- if dico['leader'] is not None:
- list_path.append(dico['leader'])
- list_path.append(dico['name'])
- return '.'.join(list_path)
+ value = dico['name']
+ else:
+ list_path = [dico['namespace'], dico['family']]
+ if dico['leader'] is not None:
+ list_path.append(dico['leader'])
+ list_path.append(dico['name'])
+ value = '.'.join(list_path)
+ if with_suffix:
+ return value, suffix
+ return value
def path_is_defined(self,
name: str,
@@ -741,10 +763,16 @@ class Path:
def _get_variable(self,
name: str,
+ with_suffix: bool=False,
) -> str:
if name not in self.variables:
if name.startswith('creole.'):
name = name.split('.')[-1]
if name not in self.variables:
+ for var_name, variable in self.variables.items():
+ if variable['is_dynamic'] and name.startswith(var_name):
+ return variable, name[len(var_name):]
raise CreoleDictConsistencyError(_('unknown option {}').format(name))
+ if with_suffix:
+ return self.variables[name], None
return self.variables[name]
diff --git a/tests/flattener_dicos/20family_dynamic_calc/00-base.xml b/tests/flattener_dicos/20family_dynamic_calc/00-base.xml
new file mode 100644
index 00000000..7fa2ca78
--- /dev/null
+++ b/tests/flattener_dicos/20family_dynamic_calc/00-base.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ val1
+ val2
+
+
+
+
+ val
+
+
+
+
+
+
+
+
+ vardynval1
+
+
+
diff --git a/tests/flattener_dicos/20family_dynamic_calc/makedict/base.json b/tests/flattener_dicos/20family_dynamic_calc/makedict/base.json
new file mode 100644
index 00000000..0f79db59
--- /dev/null
+++ b/tests/flattener_dicos/20family_dynamic_calc/makedict/base.json
@@ -0,0 +1 @@
+{"creole.general.varname": ["val1", "val2"], "creole.dynval1.vardynval1": "val", "creole.dynval2.vardynval2": "val", "creole.new.newvar": null}
diff --git a/tests/flattener_dicos/20family_dynamic_calc/result/00-base.xml b/tests/flattener_dicos/20family_dynamic_calc/result/00-base.xml
new file mode 100644
index 00000000..ed8c4a24
--- /dev/null
+++ b/tests/flattener_dicos/20family_dynamic_calc/result/00-base.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ normal
+
+ mandatory
+ normal
+ val1
+ val2
+
+
+
+ normal
+
+ mandatory
+ normal
+ val
+
+
+
+ normal
+
+ normal
+
+ creole.dyn.vardyn
+
+
+
+
+