From 7c641961d32e4590362fea43d9dc5b1f0d3c60d6 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 28 Aug 2019 15:55:10 +0200 Subject: [PATCH] better validation with parent + deepconfig --- ChangeLog | 5 +++ tests/test_metaconfig.py | 16 ++++++++ tests/test_multi_parents.py | 32 ++++++++++++++++ tiramisu/__init__.py | 2 +- tiramisu/api.py | 4 +- tiramisu/config.py | 23 ++++++----- tiramisu/locale/fr/LC_MESSAGES/tiramisu.po | 42 +++++++++++---------- tiramisu/locale/tiramisu.pot | 44 ++++++++++++---------- tiramisu/value.py | 2 +- 9 files changed, 118 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6d521e..f4980b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Aug 28 15:50:30 2019 +0200 Emmanuel Garette + * version 3.0 rc14 + * correction in metaconfig_prefix + * correction in validation with parent + Mon Aug 21 14:24:42 2019 +0200 Emmanuel Garette * version 3.0 rc12 * prefix metaconfig_prefix with current name diff --git a/tests/test_metaconfig.py b/tests/test_metaconfig.py index d561570..d564dda 100644 --- a/tests/test_metaconfig.py +++ b/tests/test_metaconfig.py @@ -745,6 +745,22 @@ def test_meta_exception_meta(): raises(Exception, "conf1.make_dict()") +def test_meta_properties_requires1(): + opt1 = BoolOption('opt1', 'opt1', False) + opt2 = BoolOption('opt2', "") + od2 = OptionDescription('od2', "", [opt2], requires=({'option': opt1, 'expected': False, 'action': 'disabled'},)) + opt3 = BoolOption('opt3', '') + opt2.impl_add_consistency('not_equal', opt3) + od = OptionDescription('root', '', [opt1, od2, opt3]) + conf1 = Config(od, session_id='conf1') + conf1.property.read_write() + meta = MetaConfig([conf1], 'meta') + meta.property.read_write() + meta.option('opt1').value.set(True) + # + conf1.option('od2.opt2').value.set(False) + + def test_meta_properties_requires_mandatory(): probes = BoolOption('probes', 'probes available', False) eth0_method = ChoiceOption('eth0_method', '', ('static', 'dhcp'), 'static') diff --git a/tests/test_multi_parents.py b/tests/test_multi_parents.py index b25b92c..257c27b 100644 --- a/tests/test_multi_parents.py +++ b/tests/test_multi_parents.py @@ -1,4 +1,6 @@ from tiramisu import IntOption, OptionDescription, MetaConfig +from tiramisu.error import ConfigError +from pytest import raises def make_metaconfig(): @@ -28,6 +30,36 @@ def test_multi_parents_path(): assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1' +def test_multi_parents_path_same(): + """ + --- metacfg2 (1) --- + metacfg1 --| | -- cfg1 + --- metacfg3 (2) --- + """ + metacfg1 = make_metaconfig() + metacfg2 = metacfg1.config.new(type='metaconfig', session_id="metacfg2") + metacfg3 = metacfg1.config.new(type='metaconfig', session_id="metacfg3") + cfg1 = metacfg2.config.new(type='config', session_id="cfg1") + metacfg3.config.add(cfg1) + # + assert metacfg2.config.path() == 'metacfg1.metacfg2' + assert metacfg3.config.path() == 'metacfg1.metacfg3' + assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1' + orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", session_id='test_cfg1') + deep = orideep + while True: + try: + children = list(deep.config.list()) + except: + break + assert len(children) < 2 + deep = children[0] + assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1' + del orideep + raises(ConfigError, "deep.config.path()") + + + def test_multi_parents_value(): metacfg1 = make_metaconfig() cfg1 = metacfg1.config.new(type='config', session_id="cfg1") diff --git a/tiramisu/__init__.py b/tiramisu/__init__.py index a83f3fc..10b3933 100644 --- a/tiramisu/__init__.py +++ b/tiramisu/__init__.py @@ -45,4 +45,4 @@ allfuncs.extend(all_options) del(all_options) __all__ = tuple(allfuncs) del(allfuncs) -__version__ = "3.0rc13" +__version__ = "3.0rc14" diff --git a/tiramisu/api.py b/tiramisu/api.py index baf4115..1b626e8 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -1354,7 +1354,7 @@ class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset): persistent=persistent, storage=storage, metaconfig_prefix=metaconfig_prefix, - deep=True)) + deep=[])) def metaconfig(self): """Get first meta configuration (obsolete please use parents)""" @@ -1420,7 +1420,7 @@ class _TiramisuContextGroupConfig(TiramisuConfig): persistent=persistent, storage=storage, metaconfig_prefix=metaconfig_prefix, - deep=True)) + deep=[])) def path(self): return self._config_bag.context.cfgimpl_get_config_path() diff --git a/tiramisu/config.py b/tiramisu/config.py index 270df47..69f8ffe 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -645,6 +645,7 @@ class _CommonConfig(SubConfig): force_settings=self.cfgimpl_get_settings(), display_name=self._display_name) fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation()) + fake_config.parents = self.parents return fake_config def duplicate(self, @@ -655,7 +656,7 @@ class _CommonConfig(SubConfig): persistent=False, metaconfig_prefix=None, child=None, - deep=False): + deep=None): assert isinstance(self, (KernelConfig, KernelMixConfig)), _('cannot duplicate {}').format(self.__class__.__name__) if isinstance(self, KernelConfig): duplicated_config = KernelConfig(self._impl_descr, @@ -691,15 +692,16 @@ class _CommonConfig(SubConfig): duplicated_config._impl_children.append(child) child.parents.append(weakref.ref(duplicated_config)) if self.parents: - if deep: - if metaconfig_prefix is not None: - metaconfig_prefix += self.impl_getname() + if deep is not None: for parent in self.parents: - duplicated_config = parent().duplicate(deep=deep, - storage=storage, - metaconfig_prefix=metaconfig_prefix, - child=duplicated_config, - persistent=persistent) + wparent = parent() + if wparent not in deep: + deep.append(wparent) + duplicated_config = wparent.duplicate(deep=deep, + storage=storage, + metaconfig_prefix=metaconfig_prefix, + child=duplicated_config, + persistent=persistent) else: duplicated_config.parents = self.parents for parent in self.parents: @@ -709,6 +711,9 @@ class _CommonConfig(SubConfig): def cfgimpl_get_config_path(self): path = self._impl_name for parent in self.parents: + wparent = parent() + if wparent is None: + raise ConfigError(_('parent of {} not already exists').format(self._impl_name)) path = parent().cfgimpl_get_config_path() + '.' + path return path diff --git a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po index 637ef4c..4fa1c87 100644 --- a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po +++ b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Tiramisu\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-19 14:10+CEST\n" +"POT-Creation-Date: 2019-08-28 15:53+CEST\n" "PO-Revision-Date: \n" "Last-Translator: Emmanuel Garette \n" "Language-Team: Tiramisu's team \n" @@ -85,7 +85,7 @@ msgstr "une propriété doit être de type frozenset" msgid "unknown when {} (must be in append or remove)" msgstr "value {} inconsistent (doit être append ou remove)" -#: tiramisu/api.py:1114 tiramisu/api.py:1136 tiramisu/config.py:1262 +#: tiramisu/api.py:1114 tiramisu/api.py:1136 tiramisu/config.py:1269 msgid "unknown type {}" msgstr "type inconnu {}" @@ -169,46 +169,50 @@ msgstr "make_dict ne peut filtrer sur une valeur mais sans option" msgid "unexpected path \"{0}\", should start with \"{1}\"" msgstr "chemin inconsistant \"{0}\", devrait commencé par \"{1}\"" -#: tiramisu/config.py:659 +#: tiramisu/config.py:660 msgid "cannot duplicate {}" msgstr "ne peut dupliquer : {0}" -#: tiramisu/config.py:748 +#: tiramisu/config.py:716 +msgid "parent of {} not already exists" +msgstr "le parent de {} n'existe plus" + +#: tiramisu/config.py:755 msgid "cannot set leadership object has root optiondescription" msgstr "ne peut assigner un objet leadership comme optiondescription racine" -#: tiramisu/config.py:750 +#: tiramisu/config.py:757 msgid "cannot set dynoptiondescription object has root optiondescription" msgstr "" "ne peut assigner un objet dynoptiondescription comme optiondescription racine" -#: tiramisu/config.py:767 tiramisu/config.py:812 +#: tiramisu/config.py:774 tiramisu/config.py:819 msgid "invalid session ID: {0} for config" msgstr "ID de session invalide : {0} pour une config" -#: tiramisu/config.py:796 +#: tiramisu/config.py:803 msgid "groupconfig's children must be a list" msgstr "enfants d'une groupconfig doit être une liste" -#: tiramisu/config.py:800 +#: tiramisu/config.py:807 msgid "groupconfig's children must be Config, MetaConfig or GroupConfig" msgstr "" "les enfants d'un groupconfig doivent être des Config, MetaConfig ou " "GroupConfig" -#: tiramisu/config.py:807 +#: tiramisu/config.py:814 msgid "config name must be uniq in groupconfig for \"{0}\"" msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\"" -#: tiramisu/config.py:977 +#: tiramisu/config.py:984 msgid "unknown config \"{}\"" msgstr "config \"{}\" inconnue" -#: tiramisu/config.py:998 +#: tiramisu/config.py:1005 msgid "child must be a Config, MixConfig or MetaConfig" msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig" -#: tiramisu/config.py:1030 +#: tiramisu/config.py:1037 msgid "" "force_default, force_default_if_same or force_dont_change_value cannot be " "set with only_config" @@ -216,34 +220,34 @@ msgstr "" "force_default, force_default_if_same ou force_dont_change_value ne peuvent " "pas être spécifié avec only_config" -#: tiramisu/config.py:1052 +#: tiramisu/config.py:1059 msgid "force_default and force_dont_change_value cannot be set together" msgstr "" "force_default et force_dont_change_value ne peuvent pas être mis ensemble" -#: tiramisu/config.py:1183 tiramisu/config.py:1260 +#: tiramisu/config.py:1190 tiramisu/config.py:1267 msgid "config name must be uniq in groupconfig for {0}" msgstr "le nom de la config doit être unique dans un groupconfig pour {0}" -#: tiramisu/config.py:1200 tiramisu/config.py:1209 +#: tiramisu/config.py:1207 tiramisu/config.py:1216 msgid "cannot find the config {}" msgstr "ne peut pas trouver la config {0}" -#: tiramisu/config.py:1231 +#: tiramisu/config.py:1238 msgid "MetaConfig with optiondescription must have string has child, not {}" msgstr "" "MetaConfig avec une optiondescription doit avoir un nom comme enfant, pas {}" -#: tiramisu/config.py:1243 +#: tiramisu/config.py:1250 msgid "child must be a Config or MetaConfig" msgstr "enfant doit être une une Config ou une MetaConfig" -#: tiramisu/config.py:1247 +#: tiramisu/config.py:1254 msgid "all config in metaconfig must have the same optiondescription" msgstr "" "toutes les configs d'une metaconfig doivent avoir la même optiondescription" -#: tiramisu/config.py:1298 +#: tiramisu/config.py:1305 msgid "metaconfig must have the same optiondescription" msgstr "metaconfig doivent avoir la même optiondescription" diff --git a/tiramisu/locale/tiramisu.pot b/tiramisu/locale/tiramisu.pot index 882498b..e32fb30 100644 --- a/tiramisu/locale/tiramisu.pot +++ b/tiramisu/locale/tiramisu.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2019-08-19 14:10+CEST\n" +"POT-Creation-Date: 2019-08-28 15:53+CEST\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -83,7 +83,7 @@ msgstr "" msgid "unknown when {} (must be in append or remove)" msgstr "" -#: tiramisu/api.py:1114 tiramisu/api.py:1136 tiramisu/config.py:1262 +#: tiramisu/api.py:1114 tiramisu/api.py:1136 tiramisu/config.py:1269 msgid "unknown type {}" msgstr "" @@ -147,71 +147,75 @@ msgstr "" msgid "unexpected path \"{0}\", should start with \"{1}\"" msgstr "" -#: tiramisu/config.py:659 +#: tiramisu/config.py:660 msgid "cannot duplicate {}" msgstr "" -#: tiramisu/config.py:748 +#: tiramisu/config.py:716 +msgid "parent of {} not already exists" +msgstr "" + +#: tiramisu/config.py:755 msgid "cannot set leadership object has root optiondescription" msgstr "" -#: tiramisu/config.py:750 +#: tiramisu/config.py:757 msgid "cannot set dynoptiondescription object has root optiondescription" msgstr "" -#: tiramisu/config.py:767 tiramisu/config.py:812 +#: tiramisu/config.py:774 tiramisu/config.py:819 msgid "invalid session ID: {0} for config" msgstr "" -#: tiramisu/config.py:796 +#: tiramisu/config.py:803 msgid "groupconfig's children must be a list" msgstr "" -#: tiramisu/config.py:800 +#: tiramisu/config.py:807 msgid "groupconfig's children must be Config, MetaConfig or GroupConfig" msgstr "" -#: tiramisu/config.py:807 +#: tiramisu/config.py:814 msgid "config name must be uniq in groupconfig for \"{0}\"" msgstr "" -#: tiramisu/config.py:977 +#: tiramisu/config.py:984 msgid "unknown config \"{}\"" msgstr "" -#: tiramisu/config.py:998 +#: tiramisu/config.py:1005 msgid "child must be a Config, MixConfig or MetaConfig" msgstr "" -#: tiramisu/config.py:1030 +#: tiramisu/config.py:1037 msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config" msgstr "" -#: tiramisu/config.py:1052 +#: tiramisu/config.py:1059 msgid "force_default and force_dont_change_value cannot be set together" msgstr "" -#: tiramisu/config.py:1183 tiramisu/config.py:1260 +#: tiramisu/config.py:1190 tiramisu/config.py:1267 msgid "config name must be uniq in groupconfig for {0}" msgstr "" -#: tiramisu/config.py:1200 tiramisu/config.py:1209 +#: tiramisu/config.py:1207 tiramisu/config.py:1216 msgid "cannot find the config {}" msgstr "" -#: tiramisu/config.py:1231 +#: tiramisu/config.py:1238 msgid "MetaConfig with optiondescription must have string has child, not {}" msgstr "" -#: tiramisu/config.py:1243 +#: tiramisu/config.py:1250 msgid "child must be a Config or MetaConfig" msgstr "" -#: tiramisu/config.py:1247 +#: tiramisu/config.py:1254 msgid "all config in metaconfig must have the same optiondescription" msgstr "" -#: tiramisu/config.py:1298 +#: tiramisu/config.py:1305 msgid "metaconfig must have the same optiondescription" msgstr "" @@ -960,7 +964,7 @@ msgstr "" #: tiramisu/storage/dictionary/storage.py:44 #: tiramisu/storage/sqlite3/storage.py:129 -msgid "session \"{}\" already used" +msgid "session \"{}\" already exists" msgstr "" #: tiramisu/storage/dictionary/storage.py:46 diff --git a/tiramisu/value.py b/tiramisu/value.py index c1667c9..e850f67 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -271,7 +271,7 @@ class Values(object): # validation will be complet in this case (consistency, ...) tested_context = context._gen_fake_values() config_bag = option_bag.config_bag.copy() - config_bag.remove_validation() + config_bag.unrestraint() config_bag.context = tested_context soption_bag = option_bag.copy() soption_bag.config_bag = config_bag