diff --git a/data/creole.dtd b/data/creole.dtd index 95cd2d45a..1b5e96f58 100644 --- a/data/creole.dtd +++ b/data/creole.dtd @@ -149,6 +149,7 @@ + @@ -166,6 +167,7 @@ + diff --git a/src/rougail/annotator.py b/src/rougail/annotator.py index 2d924f636..984aa3cf5 100644 --- a/src/rougail/annotator.py +++ b/src/rougail/annotator.py @@ -266,8 +266,12 @@ class ContainerAnnotator: disknod.permission = 'allow' def _update_file(self, file_, index, container_path): - if not hasattr(file_, 'source'): - file_.source = basename(file_.name) + if file_.name_type == "UnicodeOption": + if not hasattr(file_, 'source'): + file_.source = basename(file_.name) + elif not hasattr(file_, 'source'): + raise CreoleDictConsistencyError(_('attribute source mandatory for file with SymLinkOption name ' + 'for {}').format(file_.name)) def _split_elts(self, name, key, value, elt): """for example:: @@ -483,6 +487,7 @@ class SpaceAnnotator(object): self.remove_empty_families() self.change_variable_mode() self.change_family_mode() + self.dynamic_families() self.filter_separators() self.absolute_path_for_symlink_in_containers() self.convert_helps() @@ -611,6 +616,17 @@ class SpaceAnnotator(object): else: family.mode = mode + def dynamic_families(self): # pylint: disable=C0111 + if not hasattr(self.space, 'variables'): + return + for family in self.space.variables.values(): + if hasattr(family, 'family'): + for family in family.family.values(): + if 'dynamic' in vars(family): + namespace = self.paths.get_variable_namespace(family.dynamic) + varpath = self.paths.get_variable_path(family.dynamic, namespace) + family.dynamic = varpath + def _annotate_variable(self, variable, family_mode, path, is_follower=False): if (HIGH_COMPATIBILITY and variable.type == 'choice' and variable.mode != modes_level[-1] and variable.mandatory is True and path in self.default_has_no_value): variable.mode = modes_level[0] diff --git a/src/rougail/loader.py b/src/rougail/loader.py index 27e16597f..725094924 100644 --- a/src/rougail/loader.py +++ b/src/rougail/loader.py @@ -6,7 +6,7 @@ from os import listdir #from ast import literal_eval from lxml.etree import parse, DTD -from tiramisu.option import (StrOption, OptionDescription, PortOption, +from tiramisu.option import (StrOption, OptionDescription, DynOptionDescription, PortOption, IntOption, ChoiceOption, BoolOption, SymLinkOption, IPOption, NetworkOption, NetmaskOption, DomainnameOption, BroadcastOption, URLOption, EmailOption, FilenameOption, UsernameOption, DateOption, @@ -117,9 +117,9 @@ class PopulateTiramisuObjects(object): def make_tiramisu_objects(self, xmlroot, creolefunc_file): elt = Elt({'name': 'baseoption'}) - family = Family(elt, self.booleans, self.storage) - self.storage.add('.', family) self.eosfunc = imp.load_source('eosfunc', creolefunc_file) + family = Family(elt, self.booleans, self.storage, self.eosfunc) + self.storage.add('.', family) elts = {} for elt in xmlroot: @@ -167,7 +167,7 @@ class PopulateTiramisuObjects(object): force_icon = False else: force_icon = not subpath.startswith('containers') and not subpath.startswith('actions') - family = Family(elt, self.booleans, self.storage, force_icon) + family = Family(elt, self.booleans, self.storage, self.eosfunc, force_icon) path = self._build_path(subpath, elt) self.storage.add(path, family) return family @@ -181,7 +181,7 @@ class PopulateTiramisuObjects(object): def _iter_leader(self, leader, subpath): subpath = self._build_path(subpath, leader) - family = Family(leader, self.booleans, self.storage) + family = Family(leader, self.booleans, self.storage, self.eosfunc) family.set_leader() self.storage.add(subpath, family) leader_name = None @@ -474,7 +474,7 @@ class Variable(Common): class Family(Common): - def __init__(self, elt, booleans, storage, force_icon=False): + def __init__(self, elt, booleans, storage, eosfunc, force_icon=False): self.option = None self.attrib = {} self.is_leader = False @@ -484,6 +484,7 @@ class Family(Common): self.informations = {} self.children = [] self.storage = storage + self.eosfunc = eosfunc self.attrib['properties'] = [] for key, value in elt.attrib.items(): if key in booleans: @@ -528,11 +529,16 @@ class Family(Common): self.attrib['children'].append(child.get()) self.build_properties() try: - if not self.is_leader: + if 'dynamic' in self.attrib: + dynamic = self.storage.get(self.attrib['dynamic']).get() + del self.attrib['dynamic'] + self.attrib['suffixes'] = Calculation(self.eosfunc.calc_value, + Params((ParamOption(dynamic),))) + option = DynOptionDescription(**self.attrib) + elif not self.is_leader: option = OptionDescription(**self.attrib) else: option = Leadership(**self.attrib) - #option = OptionDescription(**self.attrib) except Exception as err: raise CreoleLoaderError(_('cannot create optiondescription {}: {}').format(self.attrib['name'], err)) for key, value in self.informations.items(): diff --git a/tests/eosfunc/test.py b/tests/eosfunc/test.py index 9aefc5827..638625f1d 100644 --- a/tests/eosfunc/test.py +++ b/tests/eosfunc/test.py @@ -1,4 +1,4 @@ -from tiramisu import valid_not_equal, valid_ip_netmask +from tiramisu import valid_not_equal, valid_ip_netmask, calc_value def calc_val(*args, **kwargs): pass diff --git a/tests/flattener_dicos/20family_dynamic/00-base.xml b/tests/flattener_dicos/20family_dynamic/00-base.xml new file mode 100644 index 000000000..26c61f0c8 --- /dev/null +++ b/tests/flattener_dicos/20family_dynamic/00-base.xml @@ -0,0 +1,15 @@ + + + + + + + val1 + val2 + + + + + + + diff --git a/tests/flattener_dicos/20family_dynamic/makedict/base.json b/tests/flattener_dicos/20family_dynamic/makedict/base.json new file mode 100644 index 000000000..64870f698 --- /dev/null +++ b/tests/flattener_dicos/20family_dynamic/makedict/base.json @@ -0,0 +1 @@ +{"creole.general.varname": ["val1", "val2"], "creole.dynval1.vardynval1": null, "creole.dynval2.vardynval2": null} \ No newline at end of file diff --git a/tests/flattener_dicos/20family_dynamic/result/00-base.xml b/tests/flattener_dicos/20family_dynamic/result/00-base.xml new file mode 100644 index 000000000..cc55d6ca9 --- /dev/null +++ b/tests/flattener_dicos/20family_dynamic/result/00-base.xml @@ -0,0 +1,20 @@ + + + + + normal + + mandatory + normal + val1 + val2 + + + + normal + + normal + + + + diff --git a/tests/flattener_dicos/70container_files_symlink_multi/00-base.xml b/tests/flattener_dicos/70container_files_symlink_multi/00-base.xml new file mode 100644 index 000000000..0b49c3b0d --- /dev/null +++ b/tests/flattener_dicos/70container_files_symlink_multi/00-base.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + /etc/mailname + /etc/mailname2 + + + + + diff --git a/tests/flattener_dicos/70container_files_symlink_multi/makedict/base.json b/tests/flattener_dicos/70container_files_symlink_multi/makedict/base.json new file mode 100644 index 000000000..e5344ac6f --- /dev/null +++ b/tests/flattener_dicos/70container_files_symlink_multi/makedict/base.json @@ -0,0 +1 @@ +{"creole.general.file_name": ["/etc/mailname", "/etc/mailname2"], "containers.container0.files.file0.mkdir": false, "containers.container0.files.file0.name": ["/etc/mailname", "/etc/mailname2"], "containers.container0.files.file0.rm": false, "containers.container0.files.file0.source": "mailname", "containers.container0.files.file0.activate": true} \ No newline at end of file diff --git a/tests/flattener_dicos/70container_files_symlink_multi/result/00-base.xml b/tests/flattener_dicos/70container_files_symlink_multi/result/00-base.xml new file mode 100644 index 000000000..ed1f44631 --- /dev/null +++ b/tests/flattener_dicos/70container_files_symlink_multi/result/00-base.xml @@ -0,0 +1,47 @@ + + + + + + + + False + + + + False + + + mailname + + + True + + + + basic + + + + + normal + + oui + non + force_default_on_freeze + frozen + hidden + mandatory + normal + oui + + + mandatory + normal + /etc/mailname + /etc/mailname2 + + + + + diff --git a/tests/flattener_dicos/80container_files_symlink_without_source/00-base.xml b/tests/flattener_dicos/80container_files_symlink_without_source/00-base.xml new file mode 100644 index 000000000..62986e0a6 --- /dev/null +++ b/tests/flattener_dicos/80container_files_symlink_without_source/00-base.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + /etc/mailname + + + + + diff --git a/tests/test_flattener.py b/tests/test_flattener.py index 6031de0b5..284ece34e 100644 --- a/tests/test_flattener.py +++ b/tests/test_flattener.py @@ -4,11 +4,9 @@ from pytest import fixture, raises from os import listdir from json import load -#from creole.xmlreflector import CreoleObjSpace, CreoleDictConsistencyError -#from creole import xmlreflector from rougail import objspace, annotator -from creole.xml_compare import xml_compare -from creole.error import CreoleDictConsistencyError +from rougail.xml_compare import xml_compare +from rougail.error import CreoleDictConsistencyError from rougail.config import dtdfilename @@ -85,7 +83,7 @@ def launch_flattener(test_dir): eolobj.save(destfile) result_file = join(test_dir, 'result/00-base.xml') if isfile(result_file): -# eolobj.save(result_file) + # eolobj.save(result_file) compare_xml(destfile, result_file) diff --git a/tests/test_makedict.py b/tests/test_makedict.py index a22af6aa7..7d410d62d 100644 --- a/tests/test_makedict.py +++ b/tests/test_makedict.py @@ -24,7 +24,7 @@ for test in listdir(dico_dirs): excludes = set([]) excludes = set([]) test_ok -= excludes -#test_ok = ['70container_all'] +#test_ok = ['20family_dynamic'] test_ok = list(test_ok) diff --git a/tests/test_template.py b/tests/test_template.py index 2b5c844de..576e6be82 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -22,13 +22,11 @@ def test_dictionary(test_dir): test_dir = join(template_dirs, test_dir) tmp_dir = join(test_dir, 'tmp') funcs_file = join(template_dirs, '../eosfunc/test.py') - template.distrib_dir = join(test_dir, 'tmpl') - template.templatedir = tmp_dir + distrib_dir = join(test_dir, 'tmpl') if isdir(tmp_dir): rmtree(tmp_dir) mkdir(tmp_dir) dest_dir = join(test_dir, 'dest') - template.dest_dir = dest_dir if isdir(dest_dir): rmtree(dest_dir) mkdir(dest_dir) @@ -41,13 +39,19 @@ def test_dictionary(test_dir): config = Config(optiondescription) config.property.read_only() template.generate(config, - funcs_file) + funcs_file, + distrib_dir, + tmp_dir, + dest_dir) - list_templates = set(listdir(dest_dir)) + if isdir(join(dest_dir, 'test')): + list_templates = set(listdir(join(dest_dir, 'test'))) + else: + list_templates = set() list_results = set(listdir(join(test_dir, 'result'))) assert list_templates == list_results for result in listdir(join(test_dir, 'result')): - template_file = join(dest_dir, result) + template_file = join(dest_dir, 'test', result) if not isfile(template_file): raise Exception(f'{template_file} is not generated') with open(join(test_dir, 'result', result), 'r') as fh: