From d3008dc2176f30285ce2f40fba6520704bc5b816 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 29 Apr 2021 18:20:05 +0200 Subject: [PATCH 1/5] disabled a service (ref #4) --- doc/service/service.md | 10 ++++++++++ src/rougail/annotator/service.py | 3 ++- src/rougail/data/rougail.dtd | 1 + .../70service_disabled/00-base.xml | 12 +++++++++++ .../70service_disabled/__init__.py | 0 .../70service_disabled/makedict/after.json | 14 +++++++++++++ .../70service_disabled/makedict/base.json | 5 +++++ .../70service_disabled/makedict/before.json | 14 +++++++++++++ .../result/systemd/system/test.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_disabled/tiramisu/base.py | 20 +++++++++++++++++++ 11 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/dictionaries/70service_disabled/00-base.xml create mode 100644 tests/dictionaries/70service_disabled/__init__.py create mode 100644 tests/dictionaries/70service_disabled/makedict/after.json create mode 100644 tests/dictionaries/70service_disabled/makedict/base.json create mode 100644 tests/dictionaries/70service_disabled/makedict/before.json create mode 120000 tests/dictionaries/70service_disabled/result/systemd/system/test.service create mode 100644 tests/dictionaries/70service_disabled/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_disabled/tiramisu/base.py diff --git a/doc/service/service.md b/doc/service/service.md index 06473ea8..de1efbaf 100644 --- a/doc/service/service.md +++ b/doc/service/service.md @@ -29,6 +29,16 @@ Un service non géré ne peut conteneur que des fichiers. ## Désactiver la génération d'un service +Il est possible de désactiver un service. Pour cela il faut rajouter l'attribut "disabled" à True : + +``` + + + +``` + +Dans ce cas, tous les services et les éléments qu'il compose ([fichier](file.md), ...) seront désactivés. + Il est possible de définir une [condition](../condition/README.md) de type "disabled_if_in" ou "disabled_if_not_in" sur une balise service : ``` diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py index de14cf9b..69158b86 100644 --- a/src/rougail/annotator/service.py +++ b/src/rougail/annotator/service.py @@ -76,10 +76,11 @@ class Annotator: None, None, 'activate', - True, + not service.disabled, service, '.'.join(['services', normalize_family(service_name), 'activate']), ) + service.disabled = None for elttype, values in dict(vars(service)).items(): if elttype == 'servicelist': self.objectspace.list_conditions.setdefault('servicelist', diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index df58c72e..1e8c6171 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -50,6 +50,7 @@ + diff --git a/tests/dictionaries/70service_disabled/00-base.xml b/tests/dictionaries/70service_disabled/00-base.xml new file mode 100644 index 00000000..f39bcf44 --- /dev/null +++ b/tests/dictionaries/70service_disabled/00-base.xml @@ -0,0 +1,12 @@ + + + + + + + + + no + + + diff --git a/tests/dictionaries/70service_disabled/__init__.py b/tests/dictionaries/70service_disabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_disabled/makedict/after.json b/tests/dictionaries/70service_disabled/makedict/after.json new file mode 100644 index 00000000..08915df9 --- /dev/null +++ b/tests/dictionaries/70service_disabled/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.condition": { + "owner": "default", + "value": "no" + }, + "services.test.activate": { + "owner": "default", + "value": false + }, + "services.test.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_disabled/makedict/base.json b/tests/dictionaries/70service_disabled/makedict/base.json new file mode 100644 index 00000000..393b57d7 --- /dev/null +++ b/tests/dictionaries/70service_disabled/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.condition": "no", + "services.test.activate": false, + "services.test.manage": true +} diff --git a/tests/dictionaries/70service_disabled/makedict/before.json b/tests/dictionaries/70service_disabled/makedict/before.json new file mode 100644 index 00000000..08915df9 --- /dev/null +++ b/tests/dictionaries/70service_disabled/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.condition": { + "owner": "default", + "value": "no" + }, + "services.test.activate": { + "owner": "default", + "value": false + }, + "services.test.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_disabled/result/systemd/system/test.service b/tests/dictionaries/70service_disabled/result/systemd/system/test.service new file mode 120000 index 00000000..dc1dc0cd --- /dev/null +++ b/tests/dictionaries/70service_disabled/result/systemd/system/test.service @@ -0,0 +1 @@ +/dev/null \ No newline at end of file diff --git a/tests/dictionaries/70service_disabled/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_disabled/result/tmpfiles.d/rougail.conf new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_disabled/tiramisu/base.py b/tests/dictionaries/70service_disabled/tiramisu/base.py new file mode 100644 index 00000000..5a830258 --- /dev/null +++ b/tests/dictionaries/70service_disabled/tiramisu/base.py @@ -0,0 +1,20 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_2 = StrOption(name="condition", doc="condition", default="no", properties=frozenset({"mandatory", "normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_5 = BoolOption(name="activate", doc="activate", default=False) +option_6 = BoolOption(name="manage", doc="manage", default=True) +option_4 = OptionDescription(name="test", doc="test", children=[option_5, option_6]) +option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_3]) From b35d930d7ef9c277d948740c0db1c3739400c643 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 1 May 2021 18:32:45 +0200 Subject: [PATCH 2/5] valid_enum is now choice --- doc/check/README.md | 1 - doc/check/valid_enum.md | 46 ------- doc/variable/README.md | 1 - doc/variable/choice.md | 28 ++++ src/rougail/annotator/check.py | 125 +----------------- src/rougail/annotator/condition.py | 2 +- src/rougail/annotator/param.py | 25 ++-- src/rougail/annotator/value.py | 17 ++- src/rougail/annotator/variable.py | 74 ++++++----- src/rougail/data/rougail.dtd | 10 +- src/rougail/objspace.py | 21 +-- src/rougail/tiramisureflector.py | 8 +- src/rougail/update.py | 107 +++++++++++++-- .../00-base.xml | 13 +- .../00-base.xml | 13 +- .../00-base.xml | 13 +- .../10load_frozenifin_multiparam/00-base.xml | 13 +- .../10load_frozenifin_noexist/00-base.xml | 13 +- .../10load_frozenifin_variable/00-base.xml | 13 +- .../10load_frozenifnotin_noexist/00-base.xml | 13 +- .../00-base.xml | 13 +- .../10valid_enum_accent/00-base.xml | 18 +-- .../10valid_enum_base/00-base.xml | 16 +-- .../00-base.xml | 14 +- .../10valid_enum_base_redefine/00-base.xml | 29 ++-- .../10valid_enum_base_redefine/01-base.xml | 12 +- .../10valid_enum_leader/00-base.xml | 16 +-- .../10valid_enum_mandatory/00-base.xml | 16 +-- .../10valid_enum_multi/00-base.xml | 16 +-- .../10valid_enum_none/00-base.xml | 16 +-- .../10valid_enum_none/tiramisu/base.py | 2 +- .../10valid_enum_number/00-base.xml | 16 +-- .../10valid_enum_numberdefault/00-base.xml | 16 +-- .../10valid_enum_param_empty/00-base.xml | 12 +- .../10valid_enum_param_empty2/00-base.xml | 12 +- .../10valid_enum_quote/00-base.xml | 16 +-- .../10valid_enum_value/00-base.xml | 16 +-- .../00-base.xml | 11 +- .../11valid_enum_function/00-base.xml | 17 +-- .../11valid_enum_variable/00-base.xml | 12 +- .../dictionaries/40ifin_validenum/00-base.xml | 13 +- .../51redefine_remove_check/00-base.xml | 16 --- .../51redefine_remove_check/01-base.xml | 10 -- .../makedict/after.json | 6 - .../makedict/base.json | 3 - .../makedict/before.json | 6 - .../51redefine_remove_check/tiramisu/base.py | 17 --- .../51redefine_validenum/00-base.xml | 16 +-- .../51redefine_validenum/01-redefine.xml | 14 +- .../extra_dirs/extra/00-base.xml | 12 +- .../60extra_help/extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 11 +- .../60extra_load/extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 14 +- .../extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/extra/00-base.xml | 12 +- .../extra_dirs/rougail/00-base.xml | 12 +- .../extra_dirs/services/00-base.xml | 12 +- .../80frozenifin_unknown/00-base.xml | 13 +- .../80valid_enum_base_redefine/00-base.xml | 32 ----- .../80valid_enum_base_redefine/01-base.xml | 17 --- .../80valid_enum_multi_param/00-base.xml | 14 +- .../80valid_enum_multi_variable/00-base.xml | 14 +- .../00-base.xml | 11 +- .../__init__.py | 0 .../errno_4 | 0 .../00-base.xml | 12 +- .../00-base.xml | 9 +- .../__init__.py | 0 .../errno_3 | 0 .../00-base.xml | 12 +- .../errno_14 | 0 .../errno_27 | 0 .../extra_dirs/extra/00-base.xml | 12 +- .../00-base.xml | 16 +-- .../__init__.py | 0 .../errno_15 | 0 .../88valid_enum_not_number/00-base.xml | 21 --- .../88valid_enum_not_number/__init__.py | 0 .../88valid_enum_not_number/errno_13 | 0 .../88valid_enum_not_number2/__init__.py | 0 .../88valid_enum_not_number2/errno_7 | 0 .../00-base.xml | 15 --- .../__init__.py | 0 .../88valid_enum_not_number_variable/errno_26 | 0 .../__init__.py | 0 .../00-base.xml | 21 --- .../__init__.py | 0 91 files changed, 556 insertions(+), 761 deletions(-) delete mode 100644 doc/check/valid_enum.md create mode 100644 doc/variable/choice.md delete mode 100644 tests/dictionaries/51redefine_remove_check/00-base.xml delete mode 100644 tests/dictionaries/51redefine_remove_check/01-base.xml delete mode 100644 tests/dictionaries/51redefine_remove_check/makedict/after.json delete mode 100644 tests/dictionaries/51redefine_remove_check/makedict/base.json delete mode 100644 tests/dictionaries/51redefine_remove_check/makedict/before.json delete mode 100644 tests/dictionaries/51redefine_remove_check/tiramisu/base.py delete mode 100644 tests/dictionaries/80valid_enum_base_redefine/00-base.xml delete mode 100644 tests/dictionaries/80valid_enum_base_redefine/01-base.xml rename tests/dictionaries/{88valid_enum_not_number2 => 80valid_enum_no_choice}/00-base.xml (60%) rename tests/dictionaries/{51redefine_remove_check => 80valid_enum_no_choice}/__init__.py (100%) rename tests/dictionaries/{80valid_enum_no_param => 80valid_enum_no_choice}/errno_4 (100%) rename tests/dictionaries/{80valid_enum_no_param => 80valid_enum_not_choice}/00-base.xml (77%) rename tests/dictionaries/{80valid_enum_base_redefine => 80valid_enum_not_choice}/__init__.py (100%) rename tests/dictionaries/{80valid_enum_base_redefine => 80valid_enum_not_choice}/errno_3 (100%) rename tests/dictionaries/{88valid_enum_variable_optional => 80valid_enum_number_without_value}/errno_14 (100%) delete mode 100644 tests/dictionaries/80valid_enum_number_without_value/errno_27 rename tests/dictionaries/{88valid_enum_numberdefaultstring => 88valid_enum_invalid_default}/00-base.xml (58%) rename tests/dictionaries/{80valid_enum_no_param => 88valid_enum_invalid_default}/__init__.py (100%) rename tests/dictionaries/{88valid_enum_numberdefaultstring => 88valid_enum_invalid_default}/errno_15 (100%) delete mode 100644 tests/dictionaries/88valid_enum_not_number/00-base.xml delete mode 100644 tests/dictionaries/88valid_enum_not_number/__init__.py delete mode 100644 tests/dictionaries/88valid_enum_not_number/errno_13 delete mode 100644 tests/dictionaries/88valid_enum_not_number2/__init__.py delete mode 100644 tests/dictionaries/88valid_enum_not_number2/errno_7 delete mode 100644 tests/dictionaries/88valid_enum_not_number_variable/00-base.xml delete mode 100644 tests/dictionaries/88valid_enum_not_number_variable/__init__.py delete mode 100644 tests/dictionaries/88valid_enum_not_number_variable/errno_26 delete mode 100644 tests/dictionaries/88valid_enum_numberdefaultstring/__init__.py delete mode 100644 tests/dictionaries/88valid_enum_variable_optional/00-base.xml delete mode 100644 tests/dictionaries/88valid_enum_variable_optional/__init__.py diff --git a/doc/check/README.md b/doc/check/README.md index 5127691d..6dd671bd 100644 --- a/doc/check/README.md +++ b/doc/check/README.md @@ -1,5 +1,4 @@ # Les vérifications des valeurs - [Fonction de vérification](function.md) - - [Les variables à choix](valid_enum.md) - [Réfinition](redefine.md) diff --git a/doc/check/valid_enum.md b/doc/check/valid_enum.md deleted file mode 100644 index 64cf29c7..00000000 --- a/doc/check/valid_enum.md +++ /dev/null @@ -1,46 +0,0 @@ -# Les variables à choix - -Une variable à choix est d'abord une variable avec une [fonction check](function.md). - -## Les variables à choix simple - -Il est possible d'imposer une liste de valeur pour une variable particulière : - -``` - - yes - no - maybe - my_variable - -``` - -Dans ce cas, seule les valeurs proposés sont possible pour cette variable. - -Par défaut, cette variable est obligatoire. Cela signifie qu'il n'est pas possible de spécifier "None" à cette variable. - -## Les variables à choix avec valeur None - -Il y a deux possibilités pour avoir une valeur "None" dans les choix : - -- rendre la variable non obligatoire, cela va ajouter un choix "None" dans la liste : - -``` - -``` - -Ou en ajoutant le paramètre "None" : - -``` - - yes - no - - maybe - my_variable - -``` - -## La valeur par défaut - -Si aucune valeur n'est spécifié pour la variable, automatiquement le premier choix va est placé comme valeur par défaut. diff --git a/doc/variable/README.md b/doc/variable/README.md index f3a1ea3a..9e5b86d2 100644 --- a/doc/variable/README.md +++ b/doc/variable/README.md @@ -116,7 +116,6 @@ Les variables booléans sont par défaut obligatoire. Pour qu'une variable bool ``` Les variables avec une valeur par défaut (non calculée) sont également automatiquement obligatoire. -[Les variables à choix](../check/valid_enum.md) sans choix "None" sont également automatiquement obligatoire. ## Valeur par défaut d'une variable diff --git a/doc/variable/choice.md b/doc/variable/choice.md new file mode 100644 index 00000000..5f5d158e --- /dev/null +++ b/doc/variable/choice.md @@ -0,0 +1,28 @@ +# Les variables à choix + +## Les variables à choix simple + +Il est possible d'imposer une liste de valeur pour une variable particulière : + +``` + + val1 + val2 + val3 + +``` + +Dans ce cas, seules les valeurs proposées sont possibles pour cette variable. Mais il est possible de mettre la valeur "None". + +## Les variables à choix avec valeur + +Si on précise une valeur, la variable passe obligatoire et la valeur "None" n'est plus autorisé : + +``` + + val1 + val2 + val3 + val1 + +``` diff --git a/src/rougail/annotator/check.py b/src/rougail/annotator/check.py index f006831c..a3949e95 100644 --- a/src/rougail/annotator/check.py +++ b/src/rougail/annotator/check.py @@ -33,7 +33,7 @@ from rougail.utils import load_modules from rougail.i18n import _ from rougail.error import DictConsistencyError, display_xmlfiles -INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier'] +INTERNAL_FUNCTIONS = ['valid_in_network', 'valid_differ', 'valid_entier'] class Annotator(TargetAnnotator, ParamAnnotator): """Annotate check @@ -58,21 +58,11 @@ class Annotator(TargetAnnotator, ParamAnnotator): self.convert_target(self.objectspace.space.constraints.check) self.convert_param(self.objectspace.space.constraints.check) self.check_check() - self.check_valid_enum() self.check_change_warning() self.convert_valid_entier() self.convert_check() del objectspace.space.constraints.check - def valid_type_validation(self, - obj, - ) -> None: - variable_type = None - if obj.name == 'valid_enum': - for target in obj.target: - variable_type = target.name.type - return variable_type - def check_check(self): # pylint: disable=R0912 """valid and manage """ @@ -87,119 +77,6 @@ class Annotator(TargetAnnotator, ParamAnnotator): for idx in remove_indexes: del self.objectspace.space.constraints.check[idx] - def check_valid_enum(self): - """verify valid_enum - """ - remove_indexes = [] - for idx, check in enumerate(self.objectspace.space.constraints.check): - if check.name != 'valid_enum': - continue - for target in check.target: - if target.name.path in self.objectspace.valid_enums: - check_xmlfiles = display_xmlfiles(self.objectspace.valid_enums\ - [target.name.path]['xmlfiles']) - msg = _(f'valid_enum already set in {check_xmlfiles} ' - f'for "{target.name.name}", you may have forget remove_check') - raise DictConsistencyError(msg, 3, check.xmlfiles) - if not hasattr(check, 'param'): - msg = _(f'param is mandatory for a valid_enum of variable "{target.name.name}"') - raise DictConsistencyError(msg, 4, check.xmlfiles) - variable_type = target.name.type - values = self._set_valid_enum(target.name, - check, - ) - if values: - if hasattr(target.name, 'value'): - # check value - self.check_valid_enum_value(target.name, values) - else: - # no value, set the first choice as default value - new_value = self.objectspace.value(check.xmlfiles) - new_value.name = values[0] - new_value.type = variable_type - target.name.value = [new_value] - remove_indexes.append(idx) - remove_indexes.sort(reverse=True) - for idx in remove_indexes: - del self.objectspace.space.constraints.check[idx] - - def _set_valid_enum(self, - variable, - check, - ) -> List[Any]: - # build choice - variable.values = [] - variable.ori_type = variable.type - variable.type = 'choice' - - has_variable = False - values = [] - has_nil = False - is_function = False - for param in check.param: - if has_variable: - msg = _(f'only one "variable" parameter is allowed for valid_enum ' - f'of variable "{variable.name}"') - raise DictConsistencyError(msg, 5, param.xmlfiles) - if param.type == 'function': - is_function = True - choice = self.objectspace.choice(variable.xmlfiles) - choice.name = param.text - choice.type = 'function' - choice.param = [] - variable.values.append(choice) - continue - if is_function: - variable.values[0].param.append(param) - continue - param_type = variable.ori_type - if param.type == 'variable': - has_variable = True - if param.optional is True: - msg = _(f'optional parameter in valid_enum for variable "{variable.name}" ' - f'is not allowed') - raise DictConsistencyError(msg, 14, param.xmlfiles) - if not param.text.multi: - msg = _(f'only multi "variable" parameter is allowed for valid_enum ' - f'of variable "{variable.name}"') - raise DictConsistencyError(msg, 6, param.xmlfiles) - param_type = 'variable' - elif param.type == 'nil': - has_nil = True - values.append(param.text) - choice = self.objectspace.choice(variable.xmlfiles) - choice.name = param.text - choice.type = param_type - variable.values.append(choice) - if is_function: - return None - if 'mandatory' not in vars(variable): - variable.mandatory = not has_nil - elif variable.mandatory is False: - choice = self.objectspace.choice(variable.xmlfiles) - choice.name = None - choice.type = 'nil' - variable.values.append(choice) - if has_variable: - return None - self.objectspace.valid_enums[variable.path] = {'type': variable.ori_type, - 'values': values, - 'xmlfiles': check.xmlfiles, - } - return values - - @staticmethod - def check_valid_enum_value(variable, - values, - ) -> None: - """check that values in valid_enum are valid - """ - for value in variable.value: - if value.name not in values: - msg = _(f'value "{value.name}" of variable "{variable.name}" is not in list ' - f'of all expected values ({values})') - raise DictConsistencyError(msg, 15, value.xmlfiles) - def check_change_warning(self): """convert level to "warnings_only" """ diff --git a/src/rougail/annotator/condition.py b/src/rougail/annotator/condition.py index ebfacbb1..790771a4 100644 --- a/src/rougail/annotator/condition.py +++ b/src/rougail/annotator/condition.py @@ -67,7 +67,7 @@ class Annotator(TargetAnnotator, ParamAnnotator, Walk): obj, ) -> None: if obj.source.type == 'choice': - return obj.source.ori_type + return None return obj.source.type def convert_auto_freeze(self): diff --git a/src/rougail/annotator/param.py b/src/rougail/annotator/param.py index f261505a..c316bb96 100644 --- a/src/rougail/annotator/param.py +++ b/src/rougail/annotator/param.py @@ -132,16 +132,17 @@ class ParamAnnotator: msg = _(f'parameter has incompatible type "{param.type}" ' f'with type "{variable_type}"') raise DictConsistencyError(msg, 7, param.xmlfiles) - try: - option = CONVERT_OPTION[variable_type] - param.text = option.get('func', str)(param.text) - getattr(tiramisu, option['opttype'])('test', - 'Object to valid value', - param.text, - **option.get('initkwargs', {}), - ) - except ValueError as err: - msg = _(f'unable to change type of value "{param.text}" ' - f'is not a valid "{variable_type}"') - raise DictConsistencyError(msg, 13, param.xmlfiles) from err + if variable_type != 'choice': + try: + option = CONVERT_OPTION[variable_type] + param.text = option.get('func', str)(param.text) + getattr(tiramisu, option['opttype'])('test', + 'Object to valid value', + param.text, + **option.get('initkwargs', {}), + ) + except ValueError as err: + msg = _(f'unable to change type of value "{param.text}" ' + f'is not a valid "{variable_type}"') + raise DictConsistencyError(msg, 13, param.xmlfiles) from err param.type = variable_type diff --git a/src/rougail/annotator/value.py b/src/rougail/annotator/value.py index 30a19246..7a8289d1 100644 --- a/src/rougail/annotator/value.py +++ b/src/rougail/annotator/value.py @@ -41,6 +41,7 @@ class Annotator(Walk): # pylint: disable=R0903 return self.objectspace = objectspace self.convert_value() + self.add_choice_nil() def convert_value(self) -> None: """convert value @@ -83,8 +84,22 @@ class Annotator(Walk): # pylint: disable=R0903 variable.default_multi = variable.value[0].name else: if len(variable.value) > 1: - msg = _(f'the non multi variable "{variable.name}" cannot have ' + msg = _(f'the none multi variable "{variable.name}" cannot have ' 'more than one value') raise DictConsistencyError(msg, 68, variable.xmlfiles) variable.default = variable.value[0].name del variable.value + + def add_choice_nil(self) -> None: + for variable in self.get_variables(): + if variable.type != 'choice': + continue + is_none = False + for choice in variable.choice: + if choice.type == 'nil': + is_none = True + if not variable.mandatory and not is_none: + choice = self.objectspace.choice(variable.xmlfiles) + choice.name = None + choice.type = 'nil' + variable.choice.append(choice) diff --git a/src/rougail/annotator/variable.py b/src/rougail/annotator/variable.py index 06392428..d6b4b677 100644 --- a/src/rougail/annotator/variable.py +++ b/src/rougail/annotator/variable.py @@ -62,11 +62,6 @@ CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), } -FORCE_CHOICE = {'schedule': ['none', 'daily', 'weekly', 'monthly'], - 'schedulemod': ['pre', 'post'], - } - - class Walk: """Walk to objectspace to find variable or family """ @@ -154,36 +149,49 @@ class Annotator(Walk): # pylint: disable=R0903 del variable.value[idx] if not variable.value: del variable.value + if hasattr(variable, 'choice'): + if variable.type != 'choice': + msg = _(f'choice for the variable "{variable.name}" not allowed with "{variable.type}" type') + raise DictConsistencyError(msg, 3, variable.xmlfiles) + values = [] + choice_type = None + for choice in variable.choice: + if choice_type == 'variable': + msg = _(f'only one "variable" choice is allowed ' + f'the variable "{variable.name}"') + raise DictConsistencyError(msg, 5, choice.xmlfiles) + if choice.type == 'nil': + choice.name = None + elif choice.type == 'variable': + choice.name = self.objectspace.paths.get_variable(choice.name) + if not choice.name.multi: + msg = _(f'only multi "variable" is allowed for a choice ' + f'of variable "{variable.name}"') + raise DictConsistencyError(msg, 6, choice.xmlfiles) + else: + if not hasattr(choice, 'name'): + msg = _(f'choice for variable "{variable.name}" must have a value') + raise DictConsistencyError(msg, 14, choice.xmlfiles) + choice.name = CONVERT_OPTION.get(choice.type, {}).get('func', str)(choice.name) + if choice_type is None: + choice_type = choice.type + values.append(choice.name) + if choice_type not in ['function', 'variable'] and hasattr(variable, 'value'): + for value in variable.value: + if value.name not in values: + msg = _(f'value "{value.name}" of variable "{variable.name}" is not in list ' + f'of all expected values ({values})') + raise DictConsistencyError(msg, 15, value.xmlfiles) + ref_choice = variable.choice[0] + self.objectspace.valid_enums[variable.path] = {'type': ref_choice.type, + 'values': values, + 'xmlfiles': ref_choice.xmlfiles, + } + elif variable.type == 'choice': + msg = _(f'choice is mandatory for the variable "{variable.name}" with choice type') + raise DictConsistencyError(msg, 4, variable.xmlfiles) variable.doc = variable.description del variable.description - self._convert_valid_enum(variable) - - def _convert_valid_enum(self, - variable, - ): - """some types are, in fact, choices - convert this kind of variables into choice - """ - if variable.type in FORCE_CHOICE: - if not hasattr(self.objectspace.space, 'constraints'): - xmlfiles = variable.xmlfiles - self.objectspace.space.constraints = self.objectspace.constraints(xmlfiles) - self.objectspace.space.constraints.namespace = variable.namespace - if not hasattr(self.objectspace.space.constraints, 'check'): - self.objectspace.space.constraints.check = [] - check = self.objectspace.check(variable.xmlfiles) - check.name = 'valid_enum' - target = self.objectspace.target(variable.xmlfiles) - target.name = variable.path - check.target = [target] - check.namespace = variable.namespace - check.param = [] - for value in FORCE_CHOICE[variable.type]: - param = self.objectspace.param(variable.xmlfiles) - param.text = value - check.param.append(param) - self.objectspace.space.constraints.check.append(check) - variable.type = 'string' def convert_test(self): """Convert variable tests value diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 1e8c6171..21329736 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -87,9 +87,9 @@ - + - + @@ -101,6 +101,7 @@ + @@ -108,6 +109,11 @@ + + + + + diff --git a/src/rougail/objspace.py b/src/rougail/objspace.py index a14ab451..dcf8c0e1 100644 --- a/src/rougail/objspace.py +++ b/src/rougail/objspace.py @@ -40,7 +40,7 @@ FORCE_UNREDEFINABLES = ('value',) # RougailObjSpace's elements that shall not be modify UNREDEFINABLE = ('multi', 'type',) # RougailObjSpace's elements that did not created automaticly -FORCE_ELEMENTS = ('choice', 'property_', 'information') +FORCE_ELEMENTS = ('property_', 'information') # XML text are convert has name FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value',) @@ -410,6 +410,8 @@ class RougailObjSpace: """Rougail object tree manipulations """ if child.tag == 'variable': + if child.attrib.get('remove_choice', False): + variableobj.choice = [] if child.attrib.get('remove_check', False): self.remove_check(variableobj.name) if child.attrib.get('remove_condition', False): @@ -424,14 +426,15 @@ class RougailObjSpace: def remove_check(self, name): """Remove a check with a specified target """ - remove_checks = [] - for idx, check in enumerate(self.space.constraints.check): # pylint: disable=E1101 - for target in check.target: - if target.name == name: - remove_checks.append(idx) - remove_checks.sort(reverse=True) - for idx in remove_checks: - self.space.constraints.check.pop(idx) # pylint: disable=E1101 + if hasattr(self.space.constraints, 'check'): + remove_checks = [] + for idx, check in enumerate(self.space.constraints.check): # pylint: disable=E1101 + for target in check.target: + if target.name == name: + remove_checks.append(idx) + remove_checks.sort(reverse=True) + for idx in remove_checks: + self.space.constraints.check.pop(idx) # pylint: disable=E1101 def remove_condition(self, name: str, diff --git a/src/rougail/tiramisureflector.py b/src/rougail/tiramisureflector.py index 9a2debc5..3de84583 100644 --- a/src/rougail/tiramisureflector.py +++ b/src/rougail/tiramisureflector.py @@ -243,7 +243,7 @@ class Common: ): """Populate variable parameters """ - if param.type in ['number', 'boolean', 'nil', 'string', 'port']: + if param.type in ['number', 'boolean', 'nil', 'string', 'port', 'choice']: value = param.text if param.type == 'string' and value is not None: value = self.convert_str(value) @@ -298,13 +298,13 @@ class Variable(Common): ): if hasattr(self.elt, 'opt'): keys['opt'] = self.elt.opt.reflector_object.get() - if hasattr(self.elt, 'values'): - values = self.elt.values + if hasattr(self.elt, 'choice'): + values = self.elt.choice if values[0].type == 'variable': value = values[0].name.reflector_object.get() keys['values'] = f"Calculation(func.calc_value, Params((ParamOption({value}))))" elif values[0].type == 'function': - keys['values'] = self.calculation_value(self.elt.values[0], []) + keys['values'] = self.calculation_value(values[0], []) else: keys['values'] = str(tuple([val.name for val in values])) if hasattr(self.elt, 'multi') and self.elt.multi: diff --git a/src/rougail/update.py b/src/rougail/update.py index b4f73488..7f90a898 100644 --- a/src/rougail/update.py +++ b/src/rougail/update.py @@ -115,20 +115,105 @@ class RougailUpgrade: variables = root.find('variables') if variables is None: return root - constraints = root.find('constraints') - if constraints is None: - return root - groups = [] - for constraint in constraints: - if constraint.tag == 'group': - constraints.remove(constraint) - groups.append(constraint) - if not groups: - return root paths = self._get_path_variables(variables, namespace == self.rougailconfig['variable_namespace'], namespace, ) + constraints = root.find('constraints') + # convert schedule and schedulemod + for variable in paths.values(): + variable = variable['variable'] + if variable.tag != 'variable': + continue + if 'type' in variable.attrib and variable.attrib['type'] in ['schedule', 'schedulemod']: + if variable.attrib['type'] == 'schedule': + choices = ('none', 'daily', 'weekly', 'monthly') + else: + choices = ('pre', 'post') + variable.attrib['type'] = 'choice' + has_value = False + for value in variable: + if value.tag == 'value': + has_value = True + break + for name in choices: + choice = SubElement(variable, 'choice') + choice.text = name + if not has_value: + value = SubElement(variable, 'value') + value.text = choices[0] + variable.attrib['mandatory'] = 'True' + + # convert choice option + valid_enums = [] + if constraints is not None: + for constraint in constraints: + if constraint.tag == 'check' and constraint.attrib['name'] == 'valid_enum': + constraints.remove(constraint) + valid_enums.append(constraint) + for valid_enum in valid_enums: + targets = [] + for target in valid_enum: + if target.tag != 'target': + continue + if target.text in paths: + # not in paths if it's optional + # but not check it + targets.append(paths[target.text]['variable']) + params = [] + function_param = None + for param in valid_enum: + if param.tag != 'param': + continue + if 'type' in param.attrib and param.attrib['type'] == 'function': + function_param = param.text + continue + params.append(param) + first_choice = None + for target in targets: + if function_param is not None: + function = SubElement(target, 'choice', type='function', name=function_param) + for param in params: + if function_param is not None: + function.append(param) + else: + choice = SubElement(target, 'choice') + if first_choice is None: + first_choice = choice + choice.text = param.text + if 'type' not in param.attrib and param.text is None: + choice_type = 'nil' + elif 'type' in param.attrib: + choice_type = param.attrib['type'] + elif 'type' in target.attrib: + choice_type = target.attrib['type'] + else: + choice_type = 'string' + choice.attrib['type'] = choice_type + has_value = False + for target in targets: + if 'remove_check' in target.attrib: + target.attrib['remove_choice'] = target.attrib['remove_check'] + for target in targets: + for value in target: + if value.tag == 'value': + has_value = True + if 'type' in target.attrib: + value.attrib['type'] = target.attrib['type'] + if first_choice is not None and not has_value: + value = SubElement(target, 'value') + value.attrib['type'] = first_choice.attrib['type'] + value.text = first_choice.text + for target in targets: + if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True': + target.attrib['type'] = 'choice' + # convert group to leadership + groups = [] + if constraints is not None: + for constraint in constraints: + if constraint.tag == 'group': + constraints.remove(constraint) + groups.append(constraint) for group in groups: if group.attrib['leader'] in paths: leader_obj = paths[group.attrib['leader']] @@ -184,6 +269,8 @@ class RougailUpgrade: subpath = path + '.' else: subpath = '' + if variable.tag not in ['variable', 'family']: + continue subpath += variable.attrib['name'] if variable.tag == 'family': self._get_path_variables(variable, is_variable_namespace, subpath, dico) diff --git a/tests/dictionaries/10frozenifin_unknown_valid_enum_number/00-base.xml b/tests/dictionaries/10frozenifin_unknown_valid_enum_number/00-base.xml index 94538cd4..0080c953 100644 --- a/tests/dictionaries/10frozenifin_unknown_valid_enum_number/00-base.xml +++ b/tests/dictionaries/10frozenifin_unknown_valid_enum_number/00-base.xml @@ -7,17 +7,16 @@ - + + 1 + 2 + 3 + 1 + - - 1 - 2 - 3 - enumvar - 4 test_variable diff --git a/tests/dictionaries/10load_disabled_if_in_variable/00-base.xml b/tests/dictionaries/10load_disabled_if_in_variable/00-base.xml index b08cdd2f..c012eb43 100644 --- a/tests/dictionaries/10load_disabled_if_in_variable/00-base.xml +++ b/tests/dictionaries/10load_disabled_if_in_variable/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun tous @@ -14,12 +17,6 @@ - - tous - authentifié - aucun - condition - mode_conteneur_actif mode_conteneur_actif2 diff --git a/tests/dictionaries/10load_disabled_if_in_variable2/00-base.xml b/tests/dictionaries/10load_disabled_if_in_variable2/00-base.xml index c8aa9b88..7d10125b 100644 --- a/tests/dictionaries/10load_disabled_if_in_variable2/00-base.xml +++ b/tests/dictionaries/10load_disabled_if_in_variable2/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun aucun @@ -14,12 +17,6 @@ - - tous - authentifié - aucun - condition - mode_conteneur_actif mode_conteneur_actif2 diff --git a/tests/dictionaries/10load_frozenifin_multiparam/00-base.xml b/tests/dictionaries/10load_frozenifin_multiparam/00-base.xml index b2f5efe2..d05dd85d 100644 --- a/tests/dictionaries/10load_frozenifin_multiparam/00-base.xml +++ b/tests/dictionaries/10load_frozenifin_multiparam/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun non @@ -14,12 +17,6 @@ - - tous - authentifié - aucun - condition - tous authentifié diff --git a/tests/dictionaries/10load_frozenifin_noexist/00-base.xml b/tests/dictionaries/10load_frozenifin_noexist/00-base.xml index 96b89e55..0abee30e 100644 --- a/tests/dictionaries/10load_frozenifin_noexist/00-base.xml +++ b/tests/dictionaries/10load_frozenifin_noexist/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun - - tous - authentifié - aucun - condition - oui non diff --git a/tests/dictionaries/10load_frozenifin_variable/00-base.xml b/tests/dictionaries/10load_frozenifin_variable/00-base.xml index d2a3fac8..6075fc78 100644 --- a/tests/dictionaries/10load_frozenifin_variable/00-base.xml +++ b/tests/dictionaries/10load_frozenifin_variable/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun tous @@ -14,12 +17,6 @@ - - tous - authentifié - aucun - condition - mode_conteneur_actif mode_conteneur_actif2 diff --git a/tests/dictionaries/10load_frozenifnotin_noexist/00-base.xml b/tests/dictionaries/10load_frozenifnotin_noexist/00-base.xml index 778d5b34..3d2d8f1c 100644 --- a/tests/dictionaries/10load_frozenifnotin_noexist/00-base.xml +++ b/tests/dictionaries/10load_frozenifnotin_noexist/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun non @@ -14,12 +17,6 @@ - - tous - authentifié - aucun - condition - oui non diff --git a/tests/dictionaries/10load_mandatoryifnotin_noexist/00-base.xml b/tests/dictionaries/10load_mandatoryifnotin_noexist/00-base.xml index 781f5e9a..4f6451f1 100644 --- a/tests/dictionaries/10load_mandatoryifnotin_noexist/00-base.xml +++ b/tests/dictionaries/10load_mandatoryifnotin_noexist/00-base.xml @@ -2,8 +2,11 @@ - - tous + + tous + tous + authentifié + aucun - - tous - authentifié - aucun - condition - oui non diff --git a/tests/dictionaries/10valid_enum_accent/00-base.xml b/tests/dictionaries/10valid_enum_accent/00-base.xml index 3c5808bc..90600804 100644 --- a/tests/dictionaries/10valid_enum_accent/00-base.xml +++ b/tests/dictionaries/10valid_enum_accent/00-base.xml @@ -7,18 +7,14 @@ - - c + + c + a + b + c + é - - - a - b - c - é - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_base/00-base.xml b/tests/dictionaries/10valid_enum_base/00-base.xml index 7b48372f..771bc0d5 100644 --- a/tests/dictionaries/10valid_enum_base/00-base.xml +++ b/tests/dictionaries/10valid_enum_base/00-base.xml @@ -7,17 +7,13 @@ - - c + + c + a + b + c - - - a - b - c - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_base_no_mandatory/00-base.xml b/tests/dictionaries/10valid_enum_base_no_mandatory/00-base.xml index 7e7b6157..d700f9d2 100644 --- a/tests/dictionaries/10valid_enum_base_no_mandatory/00-base.xml +++ b/tests/dictionaries/10valid_enum_base_no_mandatory/00-base.xml @@ -7,17 +7,13 @@ - + c + a + b + c - - - a - b - c - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_base_redefine/00-base.xml b/tests/dictionaries/10valid_enum_base_redefine/00-base.xml index 8df93848..de0c9759 100644 --- a/tests/dictionaries/10valid_enum_base_redefine/00-base.xml +++ b/tests/dictionaries/10valid_enum_base_redefine/00-base.xml @@ -7,26 +7,19 @@ - - c + + c + a + b + c - - c + + c + a + b + c - - - a - b - c - enumvar - - - a - b - c - enumvar2 - - + diff --git a/tests/dictionaries/10valid_enum_base_redefine/01-base.xml b/tests/dictionaries/10valid_enum_base_redefine/01-base.xml index 9dc00d56..bde446a7 100644 --- a/tests/dictionaries/10valid_enum_base_redefine/01-base.xml +++ b/tests/dictionaries/10valid_enum_base_redefine/01-base.xml @@ -2,16 +2,12 @@ - + c + a + c - - - a - c - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_leader/00-base.xml b/tests/dictionaries/10valid_enum_leader/00-base.xml index 55d2edd1..da141185 100644 --- a/tests/dictionaries/10valid_enum_leader/00-base.xml +++ b/tests/dictionaries/10valid_enum_leader/00-base.xml @@ -7,17 +7,15 @@ - + + a + b + c + a + - - - a - b - c - follower1 - - + diff --git a/tests/dictionaries/10valid_enum_mandatory/00-base.xml b/tests/dictionaries/10valid_enum_mandatory/00-base.xml index b7e96ff0..aa320bfb 100644 --- a/tests/dictionaries/10valid_enum_mandatory/00-base.xml +++ b/tests/dictionaries/10valid_enum_mandatory/00-base.xml @@ -8,15 +8,13 @@ - + + a + b + c + a + - - - a - b - c - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_multi/00-base.xml b/tests/dictionaries/10valid_enum_multi/00-base.xml index 54be44d1..85dae358 100644 --- a/tests/dictionaries/10valid_enum_multi/00-base.xml +++ b/tests/dictionaries/10valid_enum_multi/00-base.xml @@ -5,15 +5,13 @@ non - + + a + b + c + a + - - - a - b - c - multi - - + diff --git a/tests/dictionaries/10valid_enum_none/00-base.xml b/tests/dictionaries/10valid_enum_none/00-base.xml index b010e124..26c37a2e 100644 --- a/tests/dictionaries/10valid_enum_none/00-base.xml +++ b/tests/dictionaries/10valid_enum_none/00-base.xml @@ -7,17 +7,13 @@ - - b + + b + a + b + - - - a - b - - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_none/tiramisu/base.py b/tests/dictionaries/10valid_enum_none/tiramisu/base.py index 1625920d..f87aa2ab 100644 --- a/tests/dictionaries/10valid_enum_none/tiramisu/base.py +++ b/tests/dictionaries/10valid_enum_none/tiramisu/base.py @@ -13,7 +13,7 @@ except: from tiramisu import * option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="non", properties=frozenset({"expert", "mandatory"})) option_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"expert"})) -option_5 = ChoiceOption(name="enumvar", doc="multi", values=('a', 'b', '', None), default="b", properties=frozenset({"expert"})) +option_5 = ChoiceOption(name="enumvar", doc="multi", values=('a', 'b', None), default="b", properties=frozenset({"expert"})) option_5.impl_set_information('help', "bla bla bla") option_4 = OptionDescription(name="enumfam", doc="enumfam", children=[option_5], properties=frozenset({"expert"})) option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_4]) diff --git a/tests/dictionaries/10valid_enum_number/00-base.xml b/tests/dictionaries/10valid_enum_number/00-base.xml index 331b0df3..7c6b1463 100644 --- a/tests/dictionaries/10valid_enum_number/00-base.xml +++ b/tests/dictionaries/10valid_enum_number/00-base.xml @@ -7,15 +7,13 @@ - + + 1 + 2 + 3 + 1 + - - - 1 - 2 - 3 - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_numberdefault/00-base.xml b/tests/dictionaries/10valid_enum_numberdefault/00-base.xml index 698f4d91..76ac7138 100644 --- a/tests/dictionaries/10valid_enum_numberdefault/00-base.xml +++ b/tests/dictionaries/10valid_enum_numberdefault/00-base.xml @@ -7,17 +7,13 @@ - - 3 + + 3 + 1 + 2 + 3 - - - 1 - 2 - 3 - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_param_empty/00-base.xml b/tests/dictionaries/10valid_enum_param_empty/00-base.xml index bf3393de..1d3299e5 100644 --- a/tests/dictionaries/10valid_enum_param_empty/00-base.xml +++ b/tests/dictionaries/10valid_enum_param_empty/00-base.xml @@ -7,13 +7,11 @@ - + + + + - - - - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_param_empty2/00-base.xml b/tests/dictionaries/10valid_enum_param_empty2/00-base.xml index bf3393de..1d3299e5 100644 --- a/tests/dictionaries/10valid_enum_param_empty2/00-base.xml +++ b/tests/dictionaries/10valid_enum_param_empty2/00-base.xml @@ -7,13 +7,11 @@ - + + + + - - - - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_quote/00-base.xml b/tests/dictionaries/10valid_enum_quote/00-base.xml index c8502381..1054c9a1 100644 --- a/tests/dictionaries/10valid_enum_quote/00-base.xml +++ b/tests/dictionaries/10valid_enum_quote/00-base.xml @@ -7,15 +7,13 @@ - + + quote' + quote" + quote"' + quote' + - - - quote' - quote" - quote"' - enumvar - - + diff --git a/tests/dictionaries/10valid_enum_value/00-base.xml b/tests/dictionaries/10valid_enum_value/00-base.xml index 978e4842..4454a23d 100644 --- a/tests/dictionaries/10valid_enum_value/00-base.xml +++ b/tests/dictionaries/10valid_enum_value/00-base.xml @@ -2,17 +2,13 @@ - - b + + b + a + b + c - - - a - b - c - mode_conteneur_actif - - + diff --git a/tests/dictionaries/11disabledifnotin_filelist_notexist_validenum/00-base.xml b/tests/dictionaries/11disabledifnotin_filelist_notexist_validenum/00-base.xml index 819aee0e..74d48ad2 100644 --- a/tests/dictionaries/11disabledifnotin_filelist_notexist_validenum/00-base.xml +++ b/tests/dictionaries/11disabledifnotin_filelist_notexist_validenum/00-base.xml @@ -7,8 +7,10 @@ - - non + + non + non + statique - - non - statique - condition - statique afilllist diff --git a/tests/dictionaries/11valid_enum_function/00-base.xml b/tests/dictionaries/11valid_enum_function/00-base.xml index 52eea8d9..c7a623d6 100644 --- a/tests/dictionaries/11valid_enum_function/00-base.xml +++ b/tests/dictionaries/11valid_enum_function/00-base.xml @@ -2,17 +2,14 @@ - - 9 + + 9 + + 0 + 10 + - - - trange - 0 - 10 - var - - + diff --git a/tests/dictionaries/11valid_enum_variable/00-base.xml b/tests/dictionaries/11valid_enum_variable/00-base.xml index ed7f6d89..c758f48a 100644 --- a/tests/dictionaries/11valid_enum_variable/00-base.xml +++ b/tests/dictionaries/11valid_enum_variable/00-base.xml @@ -2,8 +2,9 @@ - - a + + a + var a @@ -12,10 +13,5 @@ - - - var - mode_conteneur_actif - - + diff --git a/tests/dictionaries/40ifin_validenum/00-base.xml b/tests/dictionaries/40ifin_validenum/00-base.xml index 3fc52d08..161e3a30 100644 --- a/tests/dictionaries/40ifin_validenum/00-base.xml +++ b/tests/dictionaries/40ifin_validenum/00-base.xml @@ -10,16 +10,15 @@ non - + + a + b + c + a + - - a - b - c - mode_conteneur_actif3 - d mode_conteneur_actif diff --git a/tests/dictionaries/51redefine_remove_check/00-base.xml b/tests/dictionaries/51redefine_remove_check/00-base.xml deleted file mode 100644 index 12f9652c..00000000 --- a/tests/dictionaries/51redefine_remove_check/00-base.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - a - b - c - mode_conteneur_actif - - - diff --git a/tests/dictionaries/51redefine_remove_check/01-base.xml b/tests/dictionaries/51redefine_remove_check/01-base.xml deleted file mode 100644 index f092eaff..00000000 --- a/tests/dictionaries/51redefine_remove_check/01-base.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - non - - - - diff --git a/tests/dictionaries/51redefine_remove_check/makedict/after.json b/tests/dictionaries/51redefine_remove_check/makedict/after.json deleted file mode 100644 index 2e6c541d..00000000 --- a/tests/dictionaries/51redefine_remove_check/makedict/after.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rougail.general.mode_conteneur_actif": { - "owner": "default", - "value": "non" - } -} diff --git a/tests/dictionaries/51redefine_remove_check/makedict/base.json b/tests/dictionaries/51redefine_remove_check/makedict/base.json deleted file mode 100644 index 25056378..00000000 --- a/tests/dictionaries/51redefine_remove_check/makedict/base.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rougail.general.mode_conteneur_actif": "non" -} diff --git a/tests/dictionaries/51redefine_remove_check/makedict/before.json b/tests/dictionaries/51redefine_remove_check/makedict/before.json deleted file mode 100644 index 2e6c541d..00000000 --- a/tests/dictionaries/51redefine_remove_check/makedict/before.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rougail.general.mode_conteneur_actif": { - "owner": "default", - "value": "non" - } -} diff --git a/tests/dictionaries/51redefine_remove_check/tiramisu/base.py b/tests/dictionaries/51redefine_remove_check/tiramisu/base.py deleted file mode 100644 index 9d70847b..00000000 --- a/tests/dictionaries/51redefine_remove_check/tiramisu/base.py +++ /dev/null @@ -1,17 +0,0 @@ -from importlib.machinery import SourceFileLoader -from importlib.util import spec_from_loader, module_from_spec -loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') -spec = spec_from_loader(loader.name, loader) -func = module_from_spec(spec) -loader.exec_module(func) -for key, value in dict(locals()).items(): - if key != ['SourceFileLoader', 'func']: - setattr(func, key, value) -try: - from tiramisu3 import * -except: - from tiramisu import * -option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="non", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) -option_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"normal"})) -option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) -option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1]) diff --git a/tests/dictionaries/51redefine_validenum/00-base.xml b/tests/dictionaries/51redefine_validenum/00-base.xml index 2e2720f2..6a2263a3 100644 --- a/tests/dictionaries/51redefine_validenum/00-base.xml +++ b/tests/dictionaries/51redefine_validenum/00-base.xml @@ -2,15 +2,13 @@ - - - - a - b - c - mode_conteneur_actif - - + diff --git a/tests/dictionaries/51redefine_validenum/01-redefine.xml b/tests/dictionaries/51redefine_validenum/01-redefine.xml index c8610c32..3e7a7635 100644 --- a/tests/dictionaries/51redefine_validenum/01-redefine.xml +++ b/tests/dictionaries/51redefine_validenum/01-redefine.xml @@ -2,14 +2,12 @@ - + + a + b + a + - - - a - b - mode_conteneur_actif - - + diff --git a/tests/dictionaries/60extra_externalspacecondition/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_externalspacecondition/extra_dirs/extra/00-base.xml index bd53c1ba..c6d59a19 100644 --- a/tests/dictionaries/60extra_externalspacecondition/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_externalspacecondition/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/60extra_help/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_help/extra_dirs/extra/00-base.xml index 7ed073cc..e55bb2f1 100644 --- a/tests/dictionaries/60extra_help/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_help/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/60extra_leadership_valid_enum/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_leadership_valid_enum/extra_dirs/extra/00-base.xml index 09f0e4b9..df8ea73d 100644 --- a/tests/dictionaries/60extra_leadership_valid_enum/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_leadership_valid_enum/extra_dirs/extra/00-base.xml @@ -6,17 +6,12 @@ test - + + pre + post pre - - - pre - post - extra.ejabberd.description.mode - - diff --git a/tests/dictionaries/60extra_load/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_load/extra_dirs/extra/00-base.xml index 3b736941..cd2c3dc4 100644 --- a/tests/dictionaries/60extra_load/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_load/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/60extra_mandatory/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_mandatory/extra_dirs/extra/00-base.xml index 32b7a5e6..3a96f5b9 100644 --- a/tests/dictionaries/60extra_mandatory/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_mandatory/extra_dirs/extra/00-base.xml @@ -5,8 +5,18 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + + pre + post + pre + diff --git a/tests/dictionaries/60extra_name_family/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_name_family/extra_dirs/extra/00-base.xml index 3b736941..cd2c3dc4 100644 --- a/tests/dictionaries/60extra_name_family/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_name_family/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/60extra_no_condition/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_no_condition/extra_dirs/extra/00-base.xml index bd53c1ba..c6d59a19 100644 --- a/tests/dictionaries/60extra_no_condition/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_no_condition/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/60extra_redefine/extra_dirs/extra/00-base.xml b/tests/dictionaries/60extra_redefine/extra_dirs/extra/00-base.xml index 3b736941..cd2c3dc4 100644 --- a/tests/dictionaries/60extra_redefine/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/60extra_redefine/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/80extra_externalspaceauto/extra_dirs/extra/00-base.xml b/tests/dictionaries/80extra_externalspaceauto/extra_dirs/extra/00-base.xml index 68a5efc4..826a52cb 100644 --- a/tests/dictionaries/80extra_externalspaceauto/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/80extra_externalspaceauto/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/80extra_externalspacecondition2/extra_dirs/extra/00-base.xml b/tests/dictionaries/80extra_externalspacecondition2/extra_dirs/extra/00-base.xml index 68a5efc4..826a52cb 100644 --- a/tests/dictionaries/80extra_externalspacecondition2/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/80extra_externalspacecondition2/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/80extra_rougail/extra_dirs/rougail/00-base.xml b/tests/dictionaries/80extra_rougail/extra_dirs/rougail/00-base.xml index 081e73b0..86ba1dcc 100644 --- a/tests/dictionaries/80extra_rougail/extra_dirs/rougail/00-base.xml +++ b/tests/dictionaries/80extra_rougail/extra_dirs/rougail/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/80extra_services/extra_dirs/services/00-base.xml b/tests/dictionaries/80extra_services/extra_dirs/services/00-base.xml index 3b736941..cd2c3dc4 100644 --- a/tests/dictionaries/80extra_services/extra_dirs/services/00-base.xml +++ b/tests/dictionaries/80extra_services/extra_dirs/services/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/80frozenifin_unknown/00-base.xml b/tests/dictionaries/80frozenifin_unknown/00-base.xml index 7e34ddd1..5e2ce3e5 100644 --- a/tests/dictionaries/80frozenifin_unknown/00-base.xml +++ b/tests/dictionaries/80frozenifin_unknown/00-base.xml @@ -7,17 +7,16 @@ - + + 1 + 2 + 3 + 1 + - - 1 - 2 - 3 - enumvar - 4 test_variable diff --git a/tests/dictionaries/80valid_enum_base_redefine/00-base.xml b/tests/dictionaries/80valid_enum_base_redefine/00-base.xml deleted file mode 100644 index 3c65e8f0..00000000 --- a/tests/dictionaries/80valid_enum_base_redefine/00-base.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - non - - - - - c - - - c - - - - - - a - b - c - enumvar - - - a - b - c - enumvar - - - diff --git a/tests/dictionaries/80valid_enum_base_redefine/01-base.xml b/tests/dictionaries/80valid_enum_base_redefine/01-base.xml deleted file mode 100644 index aae22228..00000000 --- a/tests/dictionaries/80valid_enum_base_redefine/01-base.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - c - - - - - - a - c - enumvar - - - diff --git a/tests/dictionaries/80valid_enum_multi_param/00-base.xml b/tests/dictionaries/80valid_enum_multi_param/00-base.xml index 9cd2bbef..60d9fb99 100644 --- a/tests/dictionaries/80valid_enum_multi_param/00-base.xml +++ b/tests/dictionaries/80valid_enum_multi_param/00-base.xml @@ -2,8 +2,10 @@ - - a + + a + var + d a @@ -12,11 +14,5 @@ - - - var - d - mode_conteneur_actif - - + diff --git a/tests/dictionaries/80valid_enum_multi_variable/00-base.xml b/tests/dictionaries/80valid_enum_multi_variable/00-base.xml index 355aaead..27ae8038 100644 --- a/tests/dictionaries/80valid_enum_multi_variable/00-base.xml +++ b/tests/dictionaries/80valid_enum_multi_variable/00-base.xml @@ -2,8 +2,10 @@ - - a + + a + var + var2 a @@ -17,11 +19,5 @@ - - - var - var2 - mode_conteneur_actif - - + diff --git a/tests/dictionaries/88valid_enum_not_number2/00-base.xml b/tests/dictionaries/80valid_enum_no_choice/00-base.xml similarity index 60% rename from tests/dictionaries/88valid_enum_not_number2/00-base.xml rename to tests/dictionaries/80valid_enum_no_choice/00-base.xml index 831505b1..d456318a 100644 --- a/tests/dictionaries/88valid_enum_not_number2/00-base.xml +++ b/tests/dictionaries/80valid_enum_no_choice/00-base.xml @@ -7,15 +7,10 @@ - - non + + c - - - 1 - enumvar - - + diff --git a/tests/dictionaries/51redefine_remove_check/__init__.py b/tests/dictionaries/80valid_enum_no_choice/__init__.py similarity index 100% rename from tests/dictionaries/51redefine_remove_check/__init__.py rename to tests/dictionaries/80valid_enum_no_choice/__init__.py diff --git a/tests/dictionaries/80valid_enum_no_param/errno_4 b/tests/dictionaries/80valid_enum_no_choice/errno_4 similarity index 100% rename from tests/dictionaries/80valid_enum_no_param/errno_4 rename to tests/dictionaries/80valid_enum_no_choice/errno_4 diff --git a/tests/dictionaries/80valid_enum_none_multi_variable/00-base.xml b/tests/dictionaries/80valid_enum_none_multi_variable/00-base.xml index 03e34285..780dd77d 100644 --- a/tests/dictionaries/80valid_enum_none_multi_variable/00-base.xml +++ b/tests/dictionaries/80valid_enum_none_multi_variable/00-base.xml @@ -2,18 +2,14 @@ - - a + + a + var a - - - var - mode_conteneur_actif - - + diff --git a/tests/dictionaries/80valid_enum_no_param/00-base.xml b/tests/dictionaries/80valid_enum_not_choice/00-base.xml similarity index 77% rename from tests/dictionaries/80valid_enum_no_param/00-base.xml rename to tests/dictionaries/80valid_enum_not_choice/00-base.xml index b8e7cc33..49820c22 100644 --- a/tests/dictionaries/80valid_enum_no_param/00-base.xml +++ b/tests/dictionaries/80valid_enum_not_choice/00-base.xml @@ -9,12 +9,11 @@ c + a + b + c - - - enumvar - - + diff --git a/tests/dictionaries/80valid_enum_base_redefine/__init__.py b/tests/dictionaries/80valid_enum_not_choice/__init__.py similarity index 100% rename from tests/dictionaries/80valid_enum_base_redefine/__init__.py rename to tests/dictionaries/80valid_enum_not_choice/__init__.py diff --git a/tests/dictionaries/80valid_enum_base_redefine/errno_3 b/tests/dictionaries/80valid_enum_not_choice/errno_3 similarity index 100% rename from tests/dictionaries/80valid_enum_base_redefine/errno_3 rename to tests/dictionaries/80valid_enum_not_choice/errno_3 diff --git a/tests/dictionaries/80valid_enum_number_without_value/00-base.xml b/tests/dictionaries/80valid_enum_number_without_value/00-base.xml index 7dc7ad5a..e6be9698 100644 --- a/tests/dictionaries/80valid_enum_number_without_value/00-base.xml +++ b/tests/dictionaries/80valid_enum_number_without_value/00-base.xml @@ -7,13 +7,11 @@ - + + + + - - - - enumvar - - + diff --git a/tests/dictionaries/88valid_enum_variable_optional/errno_14 b/tests/dictionaries/80valid_enum_number_without_value/errno_14 similarity index 100% rename from tests/dictionaries/88valid_enum_variable_optional/errno_14 rename to tests/dictionaries/80valid_enum_number_without_value/errno_14 diff --git a/tests/dictionaries/80valid_enum_number_without_value/errno_27 b/tests/dictionaries/80valid_enum_number_without_value/errno_27 deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/81extra_externalspace/extra_dirs/extra/00-base.xml b/tests/dictionaries/81extra_externalspace/extra_dirs/extra/00-base.xml index 68a5efc4..826a52cb 100644 --- a/tests/dictionaries/81extra_externalspace/extra_dirs/extra/00-base.xml +++ b/tests/dictionaries/81extra_externalspace/extra_dirs/extra/00-base.xml @@ -5,9 +5,17 @@ Exportation de la base de ejabberd - - + + none + daily + weekly + monthly + none + + pre + pre + post diff --git a/tests/dictionaries/88valid_enum_numberdefaultstring/00-base.xml b/tests/dictionaries/88valid_enum_invalid_default/00-base.xml similarity index 58% rename from tests/dictionaries/88valid_enum_numberdefaultstring/00-base.xml rename to tests/dictionaries/88valid_enum_invalid_default/00-base.xml index 86f9fc0b..c77fc88b 100644 --- a/tests/dictionaries/88valid_enum_numberdefaultstring/00-base.xml +++ b/tests/dictionaries/88valid_enum_invalid_default/00-base.xml @@ -7,17 +7,13 @@ - - a + + a + 1 + 2 + 3 - - - 1 - 2 - 3 - enumvar - - + diff --git a/tests/dictionaries/80valid_enum_no_param/__init__.py b/tests/dictionaries/88valid_enum_invalid_default/__init__.py similarity index 100% rename from tests/dictionaries/80valid_enum_no_param/__init__.py rename to tests/dictionaries/88valid_enum_invalid_default/__init__.py diff --git a/tests/dictionaries/88valid_enum_numberdefaultstring/errno_15 b/tests/dictionaries/88valid_enum_invalid_default/errno_15 similarity index 100% rename from tests/dictionaries/88valid_enum_numberdefaultstring/errno_15 rename to tests/dictionaries/88valid_enum_invalid_default/errno_15 diff --git a/tests/dictionaries/88valid_enum_not_number/00-base.xml b/tests/dictionaries/88valid_enum_not_number/00-base.xml deleted file mode 100644 index fde7b574..00000000 --- a/tests/dictionaries/88valid_enum_not_number/00-base.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - non - - - - - - - - - a - b - c - enumvar - - - diff --git a/tests/dictionaries/88valid_enum_not_number/__init__.py b/tests/dictionaries/88valid_enum_not_number/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_not_number/errno_13 b/tests/dictionaries/88valid_enum_not_number/errno_13 deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_not_number2/__init__.py b/tests/dictionaries/88valid_enum_not_number2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_not_number2/errno_7 b/tests/dictionaries/88valid_enum_not_number2/errno_7 deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_not_number_variable/00-base.xml b/tests/dictionaries/88valid_enum_not_number_variable/00-base.xml deleted file mode 100644 index ffa5c8c4..00000000 --- a/tests/dictionaries/88valid_enum_not_number_variable/00-base.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - str - enumvar - - - diff --git a/tests/dictionaries/88valid_enum_not_number_variable/__init__.py b/tests/dictionaries/88valid_enum_not_number_variable/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_not_number_variable/errno_26 b/tests/dictionaries/88valid_enum_not_number_variable/errno_26 deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_numberdefaultstring/__init__.py b/tests/dictionaries/88valid_enum_numberdefaultstring/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/dictionaries/88valid_enum_variable_optional/00-base.xml b/tests/dictionaries/88valid_enum_variable_optional/00-base.xml deleted file mode 100644 index 36ae120a..00000000 --- a/tests/dictionaries/88valid_enum_variable_optional/00-base.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - a - - - a - b - c - - - - - - var - mode_conteneur_actif - - - diff --git a/tests/dictionaries/88valid_enum_variable_optional/__init__.py b/tests/dictionaries/88valid_enum_variable_optional/__init__.py deleted file mode 100644 index e69de29b..00000000 From 8d32ec9f017c6d36298ecf3e8f15a4101f501bfb Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 5 May 2021 15:27:06 +0200 Subject: [PATCH 3/5] better choice documentation --- doc/variable/choice.md | 73 +++++++++++++++++-- .../10valid_enum_append/00-base.xml | 18 +++++ .../10valid_enum_append/01-base.xml | 13 ++++ .../10valid_enum_append/__init__.py | 0 .../10valid_enum_append/makedict/after.json | 10 +++ .../10valid_enum_append/makedict/base.json | 4 + .../10valid_enum_append/makedict/before.json | 10 +++ .../10valid_enum_append/tiramisu/base.py | 20 +++++ 8 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 tests/dictionaries/10valid_enum_append/00-base.xml create mode 100644 tests/dictionaries/10valid_enum_append/01-base.xml create mode 100644 tests/dictionaries/10valid_enum_append/__init__.py create mode 100644 tests/dictionaries/10valid_enum_append/makedict/after.json create mode 100644 tests/dictionaries/10valid_enum_append/makedict/base.json create mode 100644 tests/dictionaries/10valid_enum_append/makedict/before.json create mode 100644 tests/dictionaries/10valid_enum_append/tiramisu/base.py diff --git a/doc/variable/choice.md b/doc/variable/choice.md index 5f5d158e..855361be 100644 --- a/doc/variable/choice.md +++ b/doc/variable/choice.md @@ -1,6 +1,6 @@ # Les variables à choix -## Les variables à choix simple +## Une variable à choix Il est possible d'imposer une liste de valeur pour une variable particulière : @@ -12,11 +12,10 @@ Il est possible d'imposer une liste de valeur pour une variable particulière : ``` -Dans ce cas, seules les valeurs proposées sont possibles pour cette variable. Mais il est possible de mettre la valeur "None". +Dans ce cas, seules les valeurs proposées sont possibles pour cette variable. +Cette variable n'est pas obligatoire dont il est possible de mettre la valeur "None". -## Les variables à choix avec valeur - -Si on précise une valeur, la variable passe obligatoire et la valeur "None" n'est plus autorisé : +Si la variable est obligatoire ou si une valeur est précisée (la variable passe obligatoire) alors la valeur "None" n'est plus autorisé : ``` @@ -26,3 +25,67 @@ Si on précise une valeur, la variable passe obligatoire et la valeur "None" n'e val1 ``` + +## Un variable à choix typée + +Par défaut les choix sont de type "string". Il est possible de préciser des nombres, des booléens ou la valeur None : + +``` + + val1 + val2 + 3 + True + + +``` + +Comme vu précédement ajouter la valeur None n'est pas utile parce qu'elle est automatiquement ajouté si la variable n'est pas obligatoire. + +## Ajouter une option à une variable à choix existante + +Pour ajouter un choix à une variable à choix existante, rien de plus simple, juste redéfinir la variable en ajoutant le choix voulu : + +``` + + val4 + +``` + +## Redéfinir une option à choix + +Si on veut supprimer un choix ou redéfinir complètement la liste, il faut redéfinir cette variable et ajouter l'attribut "remove_choice" à "True" : + +``` + + val1 + val2 + +``` + +Dans ce cas toutes les anciens choix ne seront plus possible. Seuls les nouveaux le seront. + +## Un variable à choix provenant d'une variable + +Une variable à valeur multiple peut servir de source des choix : + +``` + + other_variable + +``` + +Dans ce cas, toutes les valeurs de la variable seront des choix utilisables par l'utilisateur. +Seul un choice de type "variable" est possible par variable. + +## Un variable à choix provenant d'une fonction + +``` + + + 0 + 10 + + 9 + +``` diff --git a/tests/dictionaries/10valid_enum_append/00-base.xml b/tests/dictionaries/10valid_enum_append/00-base.xml new file mode 100644 index 00000000..18c238b3 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/00-base.xml @@ -0,0 +1,18 @@ + + + + + + non + + + + + b + a + b + + + + + diff --git a/tests/dictionaries/10valid_enum_append/01-base.xml b/tests/dictionaries/10valid_enum_append/01-base.xml new file mode 100644 index 00000000..bf8e4389 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/01-base.xml @@ -0,0 +1,13 @@ + + + + + + c + c + + + + + + diff --git a/tests/dictionaries/10valid_enum_append/__init__.py b/tests/dictionaries/10valid_enum_append/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/10valid_enum_append/makedict/after.json b/tests/dictionaries/10valid_enum_append/makedict/after.json new file mode 100644 index 00000000..d6497f42 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/makedict/after.json @@ -0,0 +1,10 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "non" + }, + "rougail.enumfam.enumvar": { + "owner": "default", + "value": "c" + } +} diff --git a/tests/dictionaries/10valid_enum_append/makedict/base.json b/tests/dictionaries/10valid_enum_append/makedict/base.json new file mode 100644 index 00000000..58c810c5 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/makedict/base.json @@ -0,0 +1,4 @@ +{ + "rougail.general.mode_conteneur_actif": "non", + "rougail.enumfam.enumvar": "c" +} diff --git a/tests/dictionaries/10valid_enum_append/makedict/before.json b/tests/dictionaries/10valid_enum_append/makedict/before.json new file mode 100644 index 00000000..d6497f42 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/makedict/before.json @@ -0,0 +1,10 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "non" + }, + "rougail.enumfam.enumvar": { + "owner": "default", + "value": "c" + } +} diff --git a/tests/dictionaries/10valid_enum_append/tiramisu/base.py b/tests/dictionaries/10valid_enum_append/tiramisu/base.py new file mode 100644 index 00000000..0f349e81 --- /dev/null +++ b/tests/dictionaries/10valid_enum_append/tiramisu/base.py @@ -0,0 +1,20 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="non", properties=frozenset({"expert", "mandatory"})) +option_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"expert"})) +option_5 = ChoiceOption(name="enumvar", doc="multi", values=('a', 'b', 'c'), default="c", properties=frozenset({"expert", "mandatory"})) +option_5.impl_set_information('help', "bla bla bla") +option_4 = OptionDescription(name="enumfam", doc="enumfam", children=[option_5], properties=frozenset({"expert"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_4]) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1]) From 20f329d433276af5ab333291b051781b1e6b9cdc Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 6 May 2021 07:06:42 +0200 Subject: [PATCH 4/5] remove_choice only avalable for choice --- src/rougail/objspace.py | 6 +++++- tests/dictionaries/88remove_choice_not_choice/00-base.xml | 7 +++++++ tests/dictionaries/88remove_choice_not_choice/01-base.xml | 8 ++++++++ tests/dictionaries/88remove_choice_not_choice/__init__.py | 0 tests/dictionaries/88remove_choice_not_choice/errno_33 | 0 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/dictionaries/88remove_choice_not_choice/00-base.xml create mode 100644 tests/dictionaries/88remove_choice_not_choice/01-base.xml create mode 100644 tests/dictionaries/88remove_choice_not_choice/__init__.py create mode 100644 tests/dictionaries/88remove_choice_not_choice/errno_33 diff --git a/src/rougail/objspace.py b/src/rougail/objspace.py index dcf8c0e1..3be26728 100644 --- a/src/rougail/objspace.py +++ b/src/rougail/objspace.py @@ -393,7 +393,7 @@ class RougailObjSpace: for attr, val in child.attrib.items(): if redefine and attr in UNREDEFINABLE: msg = _(f'cannot redefine attribute "{attr}" for variable "{child.attrib["name"]}"' - f' in "{xmlfile}", already defined') + f' already defined') raise DictConsistencyError(msg, 48, variableobj.xmlfiles[:-1]) if attr in self.booleans_attributs: val = convert_boolean(val) @@ -411,6 +411,10 @@ class RougailObjSpace: """ if child.tag == 'variable': if child.attrib.get('remove_choice', False): + if variableobj.type != 'choice': + msg = _(f'cannot remove choices for variable "{variableobj.path}"' + f' the variable has type "{variableobj.type}"') + raise DictConsistencyError(msg, 33, variableobj.xmlfiles) variableobj.choice = [] if child.attrib.get('remove_check', False): self.remove_check(variableobj.name) diff --git a/tests/dictionaries/88remove_choice_not_choice/00-base.xml b/tests/dictionaries/88remove_choice_not_choice/00-base.xml new file mode 100644 index 00000000..57cc7646 --- /dev/null +++ b/tests/dictionaries/88remove_choice_not_choice/00-base.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/dictionaries/88remove_choice_not_choice/01-base.xml b/tests/dictionaries/88remove_choice_not_choice/01-base.xml new file mode 100644 index 00000000..f7fb6e5c --- /dev/null +++ b/tests/dictionaries/88remove_choice_not_choice/01-base.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/dictionaries/88remove_choice_not_choice/__init__.py b/tests/dictionaries/88remove_choice_not_choice/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/88remove_choice_not_choice/errno_33 b/tests/dictionaries/88remove_choice_not_choice/errno_33 new file mode 100644 index 00000000..e69de29b From 9c1589ca5399c1ca07c13555a533e15134fb76a0 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 13 May 2021 22:30:58 +0200 Subject: [PATCH 5/5] better systemd service support --- src/rougail/annotator/service.py | 54 +++++---- src/rougail/data/rougail.dtd | 3 + src/rougail/template/base.py | 65 ++++++++--- src/rougail/template/systemd.py | 90 ++++++++++----- src/rougail/update.py | 109 +++++++++--------- .../dictionaries/70service_engine/00-base.xml | 14 +++ .../dictionaries/70service_engine/__init__.py | 0 .../70service_engine/makedict/after.json | 14 +++ .../70service_engine/makedict/base.json | 5 + .../70service_engine/makedict/before.json | 14 +++ .../result/systemd/system/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_engine/tiramisu/base.py | 22 ++++ .../70service_engine/tmpl/testsrv.service | 1 + .../dictionaries/70service_mount/00-base.xml | 13 +++ .../dictionaries/70service_mount/__init__.py | 0 .../70service_mount/makedict/after.json | 14 +++ .../70service_mount/makedict/base.json | 5 + .../70service_mount/makedict/before.json | 14 +++ .../result/systemd/system/testsrv.mount | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_mount/tiramisu/base.py | 23 ++++ .../70service_mount/tmpl/testsrv.mount | 1 + .../dictionaries/70service_target/00-base.xml | 13 +++ .../dictionaries/70service_target/__init__.py | 0 .../70service_target/makedict/after.json | 14 +++ .../70service_target/makedict/base.json | 5 + .../70service_target/makedict/before.json | 14 +++ .../system/test.target.wants/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_target/tiramisu/base.py | 22 ++++ .../70service_target_engine/00-base.xml | 13 +++ .../70service_target_engine/__init__.py | 0 .../makedict/after.json | 14 +++ .../makedict/base.json | 5 + .../makedict/before.json | 14 +++ .../system/test.target.wants/testsrv.service | 1 + .../result/systemd/system/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_target_engine/tiramisu/base.py | 23 ++++ .../tmpl/testsrv.service | 1 + .../80wrong_service_name/00-base.xml | 6 + .../80wrong_service_name/__init__.py | 0 .../80wrong_service_name/errno_76 | 0 tests/test_3_template.py | 6 +- 45 files changed, 496 insertions(+), 120 deletions(-) create mode 100644 tests/dictionaries/70service_engine/00-base.xml create mode 100644 tests/dictionaries/70service_engine/__init__.py create mode 100644 tests/dictionaries/70service_engine/makedict/after.json create mode 100644 tests/dictionaries/70service_engine/makedict/base.json create mode 100644 tests/dictionaries/70service_engine/makedict/before.json create mode 100644 tests/dictionaries/70service_engine/result/systemd/system/testsrv.service create mode 100644 tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_engine/tiramisu/base.py create mode 100644 tests/dictionaries/70service_engine/tmpl/testsrv.service create mode 100644 tests/dictionaries/70service_mount/00-base.xml create mode 100644 tests/dictionaries/70service_mount/__init__.py create mode 100644 tests/dictionaries/70service_mount/makedict/after.json create mode 100644 tests/dictionaries/70service_mount/makedict/base.json create mode 100644 tests/dictionaries/70service_mount/makedict/before.json create mode 100644 tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount create mode 100644 tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_mount/tiramisu/base.py create mode 100644 tests/dictionaries/70service_mount/tmpl/testsrv.mount create mode 100644 tests/dictionaries/70service_target/00-base.xml create mode 100644 tests/dictionaries/70service_target/__init__.py create mode 100644 tests/dictionaries/70service_target/makedict/after.json create mode 100644 tests/dictionaries/70service_target/makedict/base.json create mode 100644 tests/dictionaries/70service_target/makedict/before.json create mode 120000 tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service create mode 100644 tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_target/tiramisu/base.py create mode 100644 tests/dictionaries/70service_target_engine/00-base.xml create mode 100644 tests/dictionaries/70service_target_engine/__init__.py create mode 100644 tests/dictionaries/70service_target_engine/makedict/after.json create mode 100644 tests/dictionaries/70service_target_engine/makedict/base.json create mode 100644 tests/dictionaries/70service_target_engine/makedict/before.json create mode 120000 tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service create mode 100644 tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service create mode 100644 tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_target_engine/tiramisu/base.py create mode 100644 tests/dictionaries/70service_target_engine/tmpl/testsrv.service create mode 100644 tests/dictionaries/80wrong_service_name/00-base.xml create mode 100644 tests/dictionaries/80wrong_service_name/__init__.py create mode 100644 tests/dictionaries/80wrong_service_name/errno_76 diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py index 69158b86..2f445a77 100644 --- a/src/rougail/annotator/service.py +++ b/src/rougail/annotator/service.py @@ -28,15 +28,13 @@ from os.path import basename from typing import Tuple from rougail.i18n import _ -from rougail.utils import normalize_family +from rougail.utils import normalize_family, valid_variable_family_name from rougail.error import DictConsistencyError # a object's attribute has some annotations # that shall not be present in the exported (flatened) XML -ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace', - 'remove_condition', 'path', 'instance_mode', 'index', - 'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name', - 'reflector_object',) -ALLOW_ATTRIBUT_NOT_MANAGE = ['file'] +ERASED_ATTRIBUTES = ('redefine', 'namespace', 'xmlfiles', 'disabled', 'name', 'manage') +ERASED_ATTRIBUTES2 = ('redefine', 'namespace', 'xmlfiles') +ALLOW_ATTRIBUT_NOT_MANAGE = ['file', 'engine', 'target'] class Annotator: @@ -72,6 +70,7 @@ class Annotator: self.objectspace.space.services.doc = 'services' self.objectspace.space.services.path = 'services' for service_name, service in self.objectspace.space.services.service.items(): + valid_variable_family_name(service_name, service.xmlfiles) activate_obj = self._generate_element('boolean', None, None, @@ -88,29 +87,34 @@ class Annotator: values, []).append(activate_obj) continue - if not isinstance(values, (dict, list)) or elttype in ERASED_ATTRIBUTES: + if elttype in ERASED_ATTRIBUTES: continue if not service.manage and elttype not in ALLOW_ATTRIBUT_NOT_MANAGE: msg = _(f'unmanage service cannot have "{elttype}"') raise DictConsistencyError(msg, 66, service.xmlfiles) - if elttype != 'ip': - eltname = elttype + 's' + if isinstance(values, (dict, list)): + if elttype != 'ip': + eltname = elttype + 's' + else: + eltname = elttype + path = '.'.join(['services', normalize_family(service_name), eltname]) + family = self._gen_family(eltname, + path, + service.xmlfiles, + with_informations=False, + ) + if isinstance(values, dict): + values = list(values.values()) + family.family = self.make_group_from_elts(service_name, + elttype, + values, + path, + ) + setattr(service, elttype, family) else: - eltname = elttype - path = '.'.join(['services', normalize_family(service_name), eltname]) - family = self._gen_family(eltname, - path, - service.xmlfiles, - with_informations=False, - ) - if isinstance(values, dict): - values = list(values.values()) - family.family = self.make_group_from_elts(service_name, - elttype, - values, - path, - ) - setattr(service, elttype, family) + if not hasattr(service, 'information'): + service.information = self.objectspace.information(service.xmlfiles) + setattr(service.information, elttype, values) manage = self._generate_element('boolean', None, None, @@ -157,7 +161,7 @@ class Annotator: '.'.join([subpath, 'activate']), ) for key in dir(elt): - if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES: + if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES2: continue value = getattr(elt, key) if key == listname: diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 21329736..ecb107e7 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -51,6 +51,9 @@ + + + diff --git a/src/rougail/template/base.py b/src/rougail/template/base.py index edcffaae..ff2e7abf 100644 --- a/src/rougail/template/base.py +++ b/src/rougail/template/base.py @@ -255,6 +255,7 @@ class RougailBaseTemplate: filevar: Dict, type_: str, service_name: str, + service_type: str, ) -> None: """Run templatisation on one file """ @@ -275,10 +276,11 @@ class RougailBaseTemplate: var = variable[idx] else: var = None - func = f'_instance_{type_}' + func = f'get_data_{type_}' data = getattr(self, func)(filevar, filename, service_name, + service_type, variable, idx, ) @@ -319,10 +321,26 @@ class RougailBaseTemplate: for included in (True, False): for service_obj in await self.config.option('services').list('all'): service_name = await service_obj.option.name() + service_type = await service_obj.information.get('type', 'service') if await service_obj.option('activate').value.get() is False: if included is False: - self.desactive_service(service_name) + self.desactive_service(service_name, service_type) continue + if not included: + engine = await service_obj.information.get('engine', None) + if engine: + self.instance_file({'engine': engine}, + 'service', + service_name, + service_type, + ) + target_name = await service_obj.information.get('target', None) + if target_name: + self.target_service(service_name, + target_name, + service_type, + engine is None, + ) for fills in await service_obj.list('optiondescription'): type_ = await fills.option.name() for fill_obj in await fills.list('all'): @@ -335,10 +353,14 @@ class RougailBaseTemplate: elif included is True: continue if fill['activate']: - self.instance_file(fill, type_, service_name) + self.instance_file(fill, + type_, + service_name, + service_type, + ) else: self.log.debug(_("Instantiation of file '{filename}' disabled")) - self.post_instance_service(service_name) + self.post_instance_service(service_name, service_type) self.post_instance() chdir(ori_dir) @@ -356,29 +378,42 @@ class RougailBaseTemplate: dico[key] = await obj.information.get(key, default_value) def desactive_service(self, - service_name: str, + *args, ): raise NotImplementedError(_('cannot desactivate a service')) - def post_instance_service(self, service_name): # pragma: no cover + def target_service(self, + service_name: str, + *args, + ): + raise NotImplementedError(_('cannot use target for the service {service_name}')) + + def post_instance_service(self, + *args, + ): # pragma: no cover pass def post_instance(self): # pragma: no cover pass - def _instance_ip(self, - *args, - ) -> None: # pragma: no cover + def get_data_ip(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type ip')) - def _instance_files(self, - *args, - ) -> None: # pragma: no cover + def get_data_files(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type file')) - def _instance_overrides(self, - *args, - ) -> None: # pragma: no cover + def get_data_service(self, + *args, + ) -> None: # pragma: no cover + raise NotImplementedError(_('cannot instanciate this service')) + + def get_data_overrides(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type override')) async def load_variables(self, diff --git a/src/rougail/template/systemd.py b/src/rougail/template/systemd.py index 34ba60d1..c45f6735 100644 --- a/src/rougail/template/systemd.py +++ b/src/rougail/template/systemd.py @@ -38,9 +38,13 @@ IPAddressDeny=any """ -ROUGAIL_TMPL_TEMPLATE = """%def display(%%file, %%filename) +ROUGAIL_DEST = '/usr/local/lib' +ROUGAIL_GLOBAL_SYSTEMD_FILE = '/usr/lib/systemd/system' + + +ROUGAIL_TMPL_TEMPLATE = f"""%def display(%%file, %%filename) %if %%filename.startswith('/etc/') or %%filename.startswith('/var/') or %%filename.startswith('/srv/') -C %%filename %%file.mode %%file.owner %%file.group - /usr/local/lib%%filename +C %%filename %%file.mode %%file.owner %%file.group - {ROUGAIL_DEST}%%filename z %%filename - - - - - %end if %end def @@ -70,13 +74,14 @@ class RougailSystemdTemplate(RougailBaseTemplate): self.ip_per_service = None super().__init__(config, rougailconfig) - def _instance_files(self, - filevar: Dict, - destfile: str, - service_name: str, - variable, - idx: int, - ) -> tuple: + def get_data_files(self, + filevar: Dict, + destfile: str, + service_name: str, + service_type: str, + variable, + idx: int, + ) -> tuple: source = filevar['source'] if not isfile(source): # pragma: no cover raise FileNotFound(_(f"File {source} does not exist.")) @@ -88,27 +93,30 @@ class RougailSystemdTemplate(RougailBaseTemplate): var = None return tmp_file, None, destfile, var - def _instance_overrides(self, - filevar: Dict, - destfile, - service_name: str, - *args, - ) -> tuple: + def get_data_overrides(self, + filevar: Dict, + destfile, + service_name: str, + service_type: str, + *args, + ) -> tuple: source = filevar['source'] if not isfile(source): # pragma: no cover raise FileNotFound(_(f"File {source} does not exist.")) tmp_file = join(self.tmp_dir, source) service_name = filevar['name'] - return tmp_file, None, f'/systemd/system/{service_name}.service.d/rougail.conf', None + destfile = f'/systemd/system/{service_name}.{service_type}.d/rougail.conf' + return tmp_file, None, destfile, None - def _instance_ip(self, - filevar: Dict, - ip, - service_name: str, - var: Any, - idx: int, - *args, - ) -> tuple: + def get_data_ip(self, + filevar: Dict, + ip, + service_name: str, + service_type: str, + var: Any, + idx: int, + *args, + ) -> tuple: if self.ip_per_service is None: self.ip_per_service = [] if 'netmask' in filevar: @@ -120,19 +128,49 @@ class RougailSystemdTemplate(RougailBaseTemplate): elif ip: self.ip_per_service.append(ip) + def get_data_service(self, + servicevar: Dict, + info, + service_name: str, + service_type: str, + *args, + ): + filename = f'{service_name}.{service_type}' + tmp_file = join(self.tmp_dir, filename) + var = None + destfile = f'/systemd/system/{filename}' + return tmp_file, None, destfile, var + + def desactive_service(self, service_name: str, + service_type: str, ): - filename = f'{self.destinations_dir}/systemd/system/{service_name}.service' + filename = f'{self.destinations_dir}/systemd/system/{service_name}.{service_type}' makedirs(dirname(filename), exist_ok=True) symlink('/dev/null', filename) + def target_service(self, + service_name: str, + target_name: str, + service_type: str, + global_service: str, + ): + filename = f'{self.destinations_dir}/systemd/system/{target_name}.target.wants/{service_name}.{service_type}' + makedirs(dirname(filename), exist_ok=True) + if global_service: + source_filename = f'{ROUGAIL_GLOBAL_SYSTEMD_FILE}/{service_name}.{service_type}' + else: + source_filename = f'{ROUGAIL_DEST}/systemd/system/{service_name}.{service_type}' + symlink(source_filename, filename) + def post_instance_service(self, service_name: str, + service_type: str, ) -> None: # pragma: no cover if self.ip_per_service is None: return - destfile = f'/systemd/system/{service_name}.service.d/rougail_ip.conf' + destfile = f'/systemd/system/{service_name}.{service_type}.d/rougail_ip.conf' destfilename = join(self.destinations_dir, destfile[1:]) makedirs(dirname(destfilename), exist_ok=True) self.log.info(_(f"creole processing: '{destfilename}'")) diff --git a/src/rougail/update.py b/src/rougail/update.py index 7f90a898..8ec66f43 100644 --- a/src/rougail/update.py +++ b/src/rougail/update.py @@ -144,6 +144,63 @@ class RougailUpgrade: value.text = choices[0] variable.attrib['mandatory'] = 'True' + # convert group to leadership + groups = [] + if constraints is not None: + for constraint in constraints: + if constraint.tag == 'group': + constraints.remove(constraint) + groups.append(constraint) + for group in groups: + if group.attrib['leader'] in paths: + leader_obj = paths[group.attrib['leader']] + #FIXME name peut avoir "." il faut le virer + #FIXME si extra c'est un follower ! + if 'name' in group.attrib: + grpname = group.attrib['name'] + if 'description' in group.attrib: + description = group.attrib['description'] + else: + description = grpname + else: + grpname = leader_obj['variable'].attrib['name'] + if '.' in grpname: + grpname = grpname.rsplit('.', 1)[-1] + if 'description' in group.attrib: + description = group.attrib['description'] + elif 'description' in leader_obj['variable'].attrib: + description = leader_obj['variable'].attrib['description'] + else: + description = grpname + family = SubElement(leader_obj['parent'], 'family', name=grpname, description=description, leadership="True") + leader_obj['parent'].remove(leader_obj['variable']) + family.append(leader_obj['variable']) + else: + # append in group + follower = next(iter(group)) + leader_name = group.attrib['leader'] + if '.' in leader_name: + leader_path = leader_name.rsplit('.', 1)[0] + follower_path = leader_path + '.' + follower.text + else: + follower_path = follower.text + obj = paths[follower_path] + family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True") + grpname = leader_name + for follower in group: + leader_name = group.attrib['leader'] + if '.' in leader_name: + leader_path = leader_name.rsplit('.', 1)[0] + follower_path = leader_path + '.' + follower.text + else: + follower_path = follower.text + follower_obj = paths[follower_path] + follower_obj['parent'].remove(follower_obj['variable']) + family.append(follower_obj['variable']) + if '.' in follower_path: + new_path = follower_path.rsplit('.', 1)[0] + '.' + grpname + '.' + follower_path.rsplit('.', 1)[1] + paths[new_path] = paths[follower_path] + # convert choice option valid_enums = [] if constraints is not None: @@ -207,58 +264,6 @@ class RougailUpgrade: for target in targets: if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True': target.attrib['type'] = 'choice' - # convert group to leadership - groups = [] - if constraints is not None: - for constraint in constraints: - if constraint.tag == 'group': - constraints.remove(constraint) - groups.append(constraint) - for group in groups: - if group.attrib['leader'] in paths: - leader_obj = paths[group.attrib['leader']] - #FIXME name peut avoir "." il faut le virer - #FIXME si extra c'est un follower ! - if 'name' in group.attrib: - name = group.attrib['name'] - if 'description' in group.attrib: - description = group.attrib['description'] - else: - description = name - else: - name = leader_obj['variable'].attrib['name'] - if '.' in name: - name = name.rsplit('.', 1)[-1] - if 'description' in group.attrib: - description = group.attrib['description'] - elif 'description' in leader_obj['variable'].attrib: - description = leader_obj['variable'].attrib['description'] - else: - description = name - family = SubElement(leader_obj['parent'], 'family', name=name, description=description, leadership="True") - leader_obj['parent'].remove(leader_obj['variable']) - family.append(leader_obj['variable']) - else: - # append in group - follower = next(iter(group)) - leader_name = group.attrib['leader'] - if '.' in leader_name: - leader_path = leader_name.rsplit('.', 1)[0] - follower_path = leader_path + '.' + follower.text - else: - follower_path = follower.text - obj = paths[follower_path] - family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True") - for follower in group: - leader_name = group.attrib['leader'] - if '.' in leader_name: - leader_path = leader_name.rsplit('.', 1)[0] - follower_path = leader_path + '.' + follower.text - else: - follower_path = follower.text - follower_obj = paths[follower_path] - follower_obj['parent'].remove(follower_obj['variable']) - family.append(follower_obj['variable']) return root def _get_path_variables(self, variables, is_variable_namespace, path, dico=None): diff --git a/tests/dictionaries/70service_engine/00-base.xml b/tests/dictionaries/70service_engine/00-base.xml new file mode 100644 index 00000000..a84500bd --- /dev/null +++ b/tests/dictionaries/70service_engine/00-base.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tests/dictionaries/70service_engine/__init__.py b/tests/dictionaries/70service_engine/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_engine/makedict/after.json b/tests/dictionaries/70service_engine/makedict/after.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_engine/makedict/base.json b/tests/dictionaries/70service_engine/makedict/base.json new file mode 100644 index 00000000..d89ef3da --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_engine/makedict/before.json b/tests/dictionaries/70service_engine/makedict/before.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service b/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service new file mode 100644 index 00000000..bd51bf63 --- /dev/null +++ b/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service @@ -0,0 +1 @@ +oui diff --git a/tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_engine/tiramisu/base.py b/tests/dictionaries/70service_engine/tiramisu/base.py new file mode 100644 index 00000000..bbf9ec62 --- /dev/null +++ b/tests/dictionaries/70service_engine/tiramisu/base.py @@ -0,0 +1,22 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('engine', "creole") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_engine/tmpl/testsrv.service b/tests/dictionaries/70service_engine/tmpl/testsrv.service new file mode 100644 index 00000000..a29cfeaf --- /dev/null +++ b/tests/dictionaries/70service_engine/tmpl/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_mount/00-base.xml b/tests/dictionaries/70service_mount/00-base.xml new file mode 100644 index 00000000..92889e45 --- /dev/null +++ b/tests/dictionaries/70service_mount/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_mount/__init__.py b/tests/dictionaries/70service_mount/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_mount/makedict/after.json b/tests/dictionaries/70service_mount/makedict/after.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_mount/makedict/base.json b/tests/dictionaries/70service_mount/makedict/base.json new file mode 100644 index 00000000..d89ef3da --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_mount/makedict/before.json b/tests/dictionaries/70service_mount/makedict/before.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount b/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount new file mode 100644 index 00000000..bd51bf63 --- /dev/null +++ b/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount @@ -0,0 +1 @@ +oui diff --git a/tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_mount/tiramisu/base.py b/tests/dictionaries/70service_mount/tiramisu/base.py new file mode 100644 index 00000000..5f477671 --- /dev/null +++ b/tests/dictionaries/70service_mount/tiramisu/base.py @@ -0,0 +1,23 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('type', "mount") +option_5.impl_set_information('engine', "creole") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_mount/tmpl/testsrv.mount b/tests/dictionaries/70service_mount/tmpl/testsrv.mount new file mode 100644 index 00000000..a29cfeaf --- /dev/null +++ b/tests/dictionaries/70service_mount/tmpl/testsrv.mount @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_target/00-base.xml b/tests/dictionaries/70service_target/00-base.xml new file mode 100644 index 00000000..9d0494a2 --- /dev/null +++ b/tests/dictionaries/70service_target/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_target/__init__.py b/tests/dictionaries/70service_target/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_target/makedict/after.json b/tests/dictionaries/70service_target/makedict/after.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target/makedict/base.json b/tests/dictionaries/70service_target/makedict/base.json new file mode 100644 index 00000000..d89ef3da --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_target/makedict/before.json b/tests/dictionaries/70service_target/makedict/before.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service b/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service new file mode 120000 index 00000000..c8a38933 --- /dev/null +++ b/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/testsrv.service \ No newline at end of file diff --git a/tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_target/tiramisu/base.py b/tests/dictionaries/70service_target/tiramisu/base.py new file mode 100644 index 00000000..4795e3b3 --- /dev/null +++ b/tests/dictionaries/70service_target/tiramisu/base.py @@ -0,0 +1,22 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('target', "test") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_target_engine/00-base.xml b/tests/dictionaries/70service_target_engine/00-base.xml new file mode 100644 index 00000000..313e8062 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_target_engine/__init__.py b/tests/dictionaries/70service_target_engine/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_target_engine/makedict/after.json b/tests/dictionaries/70service_target_engine/makedict/after.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target_engine/makedict/base.json b/tests/dictionaries/70service_target_engine/makedict/base.json new file mode 100644 index 00000000..d89ef3da --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_target_engine/makedict/before.json b/tests/dictionaries/70service_target_engine/makedict/before.json new file mode 100644 index 00000000..c8847b43 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service b/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service new file mode 120000 index 00000000..4cc00d1a --- /dev/null +++ b/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service @@ -0,0 +1 @@ +/usr/local/lib/systemd/system/testsrv.service \ No newline at end of file diff --git a/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service b/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service new file mode 100644 index 00000000..a29cfeaf --- /dev/null +++ b/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/70service_target_engine/tiramisu/base.py b/tests/dictionaries/70service_target_engine/tiramisu/base.py new file mode 100644 index 00000000..4701a3b1 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/tiramisu/base.py @@ -0,0 +1,23 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('target', "test") +option_5.impl_set_information('engine', "none") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_target_engine/tmpl/testsrv.service b/tests/dictionaries/70service_target_engine/tmpl/testsrv.service new file mode 100644 index 00000000..a29cfeaf --- /dev/null +++ b/tests/dictionaries/70service_target_engine/tmpl/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/80wrong_service_name/00-base.xml b/tests/dictionaries/80wrong_service_name/00-base.xml new file mode 100644 index 00000000..a7f31c93 --- /dev/null +++ b/tests/dictionaries/80wrong_service_name/00-base.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/dictionaries/80wrong_service_name/__init__.py b/tests/dictionaries/80wrong_service_name/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/80wrong_service_name/errno_76 b/tests/dictionaries/80wrong_service_name/errno_76 new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_3_template.py b/tests/test_3_template.py index 1bb423df..6ac69cee 100644 --- a/tests/test_3_template.py +++ b/tests/test_3_template.py @@ -1,4 +1,4 @@ -from os import listdir, mkdir +from os import listdir, mkdir, readlink from os.path import join, isdir, isfile, islink from shutil import rmtree from pytest import fixture, mark @@ -82,7 +82,9 @@ async def test_dictionary(test_dir): assert list_templates == list_results for result in list_results: template_file = join(dest_dir, result) - if islink(template_file) and islink(join(test_dir, 'result', result)): + assert islink(template_file) == islink(join(test_dir, 'result', result)) + if islink(template_file): + assert readlink(template_file) == readlink(join(test_dir, 'result', result)) continue if not isfile(template_file): raise Exception(f'{template_file} is not generated')