better validation with parent + deepconfig

This commit is contained in:
Emmanuel Garette 2019-08-28 15:55:10 +02:00
parent 4321bde399
commit 7c641961d3
9 changed files with 118 additions and 52 deletions

View file

@ -1,3 +1,8 @@
Wed Aug 28 15:50:30 2019 +0200 Emmanuel Garette <egarette@cadoles.com>
* version 3.0 rc14
* correction in metaconfig_prefix
* correction in validation with parent
Mon Aug 21 14:24:42 2019 +0200 Emmanuel Garette <egarette@cadoles.com> Mon Aug 21 14:24:42 2019 +0200 Emmanuel Garette <egarette@cadoles.com>
* version 3.0 rc12 * version 3.0 rc12
* prefix metaconfig_prefix with current name * prefix metaconfig_prefix with current name

View file

@ -745,6 +745,22 @@ def test_meta_exception_meta():
raises(Exception, "conf1.make_dict()") 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(): def test_meta_properties_requires_mandatory():
probes = BoolOption('probes', 'probes available', False) probes = BoolOption('probes', 'probes available', False)
eth0_method = ChoiceOption('eth0_method', '', ('static', 'dhcp'), 'static') eth0_method = ChoiceOption('eth0_method', '', ('static', 'dhcp'), 'static')

View file

@ -1,4 +1,6 @@
from tiramisu import IntOption, OptionDescription, MetaConfig from tiramisu import IntOption, OptionDescription, MetaConfig
from tiramisu.error import ConfigError
from pytest import raises
def make_metaconfig(): def make_metaconfig():
@ -28,6 +30,36 @@ def test_multi_parents_path():
assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1' 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(): def test_multi_parents_value():
metacfg1 = make_metaconfig() metacfg1 = make_metaconfig()
cfg1 = metacfg1.config.new(type='config', session_id="cfg1") cfg1 = metacfg1.config.new(type='config', session_id="cfg1")

View file

@ -45,4 +45,4 @@ allfuncs.extend(all_options)
del(all_options) del(all_options)
__all__ = tuple(allfuncs) __all__ = tuple(allfuncs)
del(allfuncs) del(allfuncs)
__version__ = "3.0rc13" __version__ = "3.0rc14"

View file

@ -1354,7 +1354,7 @@ class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset):
persistent=persistent, persistent=persistent,
storage=storage, storage=storage,
metaconfig_prefix=metaconfig_prefix, metaconfig_prefix=metaconfig_prefix,
deep=True)) deep=[]))
def metaconfig(self): def metaconfig(self):
"""Get first meta configuration (obsolete please use parents)""" """Get first meta configuration (obsolete please use parents)"""
@ -1420,7 +1420,7 @@ class _TiramisuContextGroupConfig(TiramisuConfig):
persistent=persistent, persistent=persistent,
storage=storage, storage=storage,
metaconfig_prefix=metaconfig_prefix, metaconfig_prefix=metaconfig_prefix,
deep=True)) deep=[]))
def path(self): def path(self):
return self._config_bag.context.cfgimpl_get_config_path() return self._config_bag.context.cfgimpl_get_config_path()

View file

@ -645,6 +645,7 @@ class _CommonConfig(SubConfig):
force_settings=self.cfgimpl_get_settings(), force_settings=self.cfgimpl_get_settings(),
display_name=self._display_name) display_name=self._display_name)
fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation()) fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
fake_config.parents = self.parents
return fake_config return fake_config
def duplicate(self, def duplicate(self,
@ -655,7 +656,7 @@ class _CommonConfig(SubConfig):
persistent=False, persistent=False,
metaconfig_prefix=None, metaconfig_prefix=None,
child=None, child=None,
deep=False): deep=None):
assert isinstance(self, (KernelConfig, KernelMixConfig)), _('cannot duplicate {}').format(self.__class__.__name__) assert isinstance(self, (KernelConfig, KernelMixConfig)), _('cannot duplicate {}').format(self.__class__.__name__)
if isinstance(self, KernelConfig): if isinstance(self, KernelConfig):
duplicated_config = KernelConfig(self._impl_descr, duplicated_config = KernelConfig(self._impl_descr,
@ -691,11 +692,12 @@ class _CommonConfig(SubConfig):
duplicated_config._impl_children.append(child) duplicated_config._impl_children.append(child)
child.parents.append(weakref.ref(duplicated_config)) child.parents.append(weakref.ref(duplicated_config))
if self.parents: if self.parents:
if deep: if deep is not None:
if metaconfig_prefix is not None:
metaconfig_prefix += self.impl_getname()
for parent in self.parents: for parent in self.parents:
duplicated_config = parent().duplicate(deep=deep, wparent = parent()
if wparent not in deep:
deep.append(wparent)
duplicated_config = wparent.duplicate(deep=deep,
storage=storage, storage=storage,
metaconfig_prefix=metaconfig_prefix, metaconfig_prefix=metaconfig_prefix,
child=duplicated_config, child=duplicated_config,
@ -709,6 +711,9 @@ class _CommonConfig(SubConfig):
def cfgimpl_get_config_path(self): def cfgimpl_get_config_path(self):
path = self._impl_name path = self._impl_name
for parent in self.parents: 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 path = parent().cfgimpl_get_config_path() + '.' + path
return path return path

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tiramisu\n" "Project-Id-Version: Tiramisu\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: \n"
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n" "Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n" "Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
@ -85,7 +85,7 @@ msgstr "une propriété doit être de type frozenset"
msgid "unknown when {} (must be in append or remove)" msgid "unknown when {} (must be in append or remove)"
msgstr "value {} inconsistent (doit être append ou 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 {}" msgid "unknown type {}"
msgstr "type inconnu {}" 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}\"" msgid "unexpected path \"{0}\", should start with \"{1}\""
msgstr "chemin inconsistant \"{0}\", devrait commencé par \"{1}\"" msgstr "chemin inconsistant \"{0}\", devrait commencé par \"{1}\""
#: tiramisu/config.py:659 #: tiramisu/config.py:660
msgid "cannot duplicate {}" msgid "cannot duplicate {}"
msgstr "ne peut dupliquer : {0}" 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" msgid "cannot set leadership object has root optiondescription"
msgstr "ne peut assigner un objet leadership comme optiondescription racine" 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" msgid "cannot set dynoptiondescription object has root optiondescription"
msgstr "" msgstr ""
"ne peut assigner un objet dynoptiondescription comme optiondescription racine" "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" msgid "invalid session ID: {0} for config"
msgstr "ID de session invalide : {0} pour une 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" msgid "groupconfig's children must be a list"
msgstr "enfants d'une groupconfig doit être une liste" 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" msgid "groupconfig's children must be Config, MetaConfig or GroupConfig"
msgstr "" msgstr ""
"les enfants d'un groupconfig doivent être des Config, MetaConfig ou " "les enfants d'un groupconfig doivent être des Config, MetaConfig ou "
"GroupConfig" "GroupConfig"
#: tiramisu/config.py:807 #: tiramisu/config.py:814
msgid "config name must be uniq in groupconfig for \"{0}\"" msgid "config name must be uniq in groupconfig for \"{0}\""
msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{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 \"{}\"" msgid "unknown config \"{}\""
msgstr "config \"{}\" inconnue" msgstr "config \"{}\" inconnue"
#: tiramisu/config.py:998 #: tiramisu/config.py:1005
msgid "child must be a Config, MixConfig or MetaConfig" msgid "child must be a Config, MixConfig or MetaConfig"
msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig" msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig"
#: tiramisu/config.py:1030 #: tiramisu/config.py:1037
msgid "" msgid ""
"force_default, force_default_if_same or force_dont_change_value cannot be " "force_default, force_default_if_same or force_dont_change_value cannot be "
"set with only_config" "set with only_config"
@ -216,34 +220,34 @@ msgstr ""
"force_default, force_default_if_same ou force_dont_change_value ne peuvent " "force_default, force_default_if_same ou force_dont_change_value ne peuvent "
"pas être spécifié avec only_config" "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" msgid "force_default and force_dont_change_value cannot be set together"
msgstr "" msgstr ""
"force_default et force_dont_change_value ne peuvent pas être mis ensemble" "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}" msgid "config name must be uniq in groupconfig for {0}"
msgstr "le nom de la config doit être unique dans un groupconfig pour {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 {}" msgid "cannot find the config {}"
msgstr "ne peut pas trouver la config {0}" 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 {}" msgid "MetaConfig with optiondescription must have string has child, not {}"
msgstr "" msgstr ""
"MetaConfig avec une optiondescription doit avoir un nom comme enfant, pas {}" "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" msgid "child must be a Config or MetaConfig"
msgstr "enfant doit être une une Config ou une 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" msgid "all config in metaconfig must have the same optiondescription"
msgstr "" msgstr ""
"toutes les configs d'une metaconfig doivent avoir la même optiondescription" "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" msgid "metaconfig must have the same optiondescription"
msgstr "metaconfig doivent avoir la même optiondescription" msgstr "metaconfig doivent avoir la même optiondescription"

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -83,7 +83,7 @@ msgstr ""
msgid "unknown when {} (must be in append or remove)" msgid "unknown when {} (must be in append or remove)"
msgstr "" 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 {}" msgid "unknown type {}"
msgstr "" msgstr ""
@ -147,71 +147,75 @@ msgstr ""
msgid "unexpected path \"{0}\", should start with \"{1}\"" msgid "unexpected path \"{0}\", should start with \"{1}\""
msgstr "" msgstr ""
#: tiramisu/config.py:659 #: tiramisu/config.py:660
msgid "cannot duplicate {}" msgid "cannot duplicate {}"
msgstr "" 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" msgid "cannot set leadership object has root optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:750 #: tiramisu/config.py:757
msgid "cannot set dynoptiondescription object has root optiondescription" msgid "cannot set dynoptiondescription object has root optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:767 tiramisu/config.py:812 #: tiramisu/config.py:774 tiramisu/config.py:819
msgid "invalid session ID: {0} for config" msgid "invalid session ID: {0} for config"
msgstr "" msgstr ""
#: tiramisu/config.py:796 #: tiramisu/config.py:803
msgid "groupconfig's children must be a list" msgid "groupconfig's children must be a list"
msgstr "" msgstr ""
#: tiramisu/config.py:800 #: tiramisu/config.py:807
msgid "groupconfig's children must be Config, MetaConfig or GroupConfig" msgid "groupconfig's children must be Config, MetaConfig or GroupConfig"
msgstr "" msgstr ""
#: tiramisu/config.py:807 #: tiramisu/config.py:814
msgid "config name must be uniq in groupconfig for \"{0}\"" msgid "config name must be uniq in groupconfig for \"{0}\""
msgstr "" msgstr ""
#: tiramisu/config.py:977 #: tiramisu/config.py:984
msgid "unknown config \"{}\"" msgid "unknown config \"{}\""
msgstr "" msgstr ""
#: tiramisu/config.py:998 #: tiramisu/config.py:1005
msgid "child must be a Config, MixConfig or MetaConfig" msgid "child must be a Config, MixConfig or MetaConfig"
msgstr "" 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" msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config"
msgstr "" msgstr ""
#: tiramisu/config.py:1052 #: tiramisu/config.py:1059
msgid "force_default and force_dont_change_value cannot be set together" msgid "force_default and force_dont_change_value cannot be set together"
msgstr "" 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}" msgid "config name must be uniq in groupconfig for {0}"
msgstr "" msgstr ""
#: tiramisu/config.py:1200 tiramisu/config.py:1209 #: tiramisu/config.py:1207 tiramisu/config.py:1216
msgid "cannot find the config {}" msgid "cannot find the config {}"
msgstr "" msgstr ""
#: tiramisu/config.py:1231 #: tiramisu/config.py:1238
msgid "MetaConfig with optiondescription must have string has child, not {}" msgid "MetaConfig with optiondescription must have string has child, not {}"
msgstr "" msgstr ""
#: tiramisu/config.py:1243 #: tiramisu/config.py:1250
msgid "child must be a Config or MetaConfig" msgid "child must be a Config or MetaConfig"
msgstr "" msgstr ""
#: tiramisu/config.py:1247 #: tiramisu/config.py:1254
msgid "all config in metaconfig must have the same optiondescription" msgid "all config in metaconfig must have the same optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:1298 #: tiramisu/config.py:1305
msgid "metaconfig must have the same optiondescription" msgid "metaconfig must have the same optiondescription"
msgstr "" msgstr ""
@ -960,7 +964,7 @@ msgstr ""
#: tiramisu/storage/dictionary/storage.py:44 #: tiramisu/storage/dictionary/storage.py:44
#: tiramisu/storage/sqlite3/storage.py:129 #: tiramisu/storage/sqlite3/storage.py:129
msgid "session \"{}\" already used" msgid "session \"{}\" already exists"
msgstr "" msgstr ""
#: tiramisu/storage/dictionary/storage.py:46 #: tiramisu/storage/dictionary/storage.py:46

View file

@ -271,7 +271,7 @@ class Values(object):
# validation will be complet in this case (consistency, ...) # validation will be complet in this case (consistency, ...)
tested_context = context._gen_fake_values() tested_context = context._gen_fake_values()
config_bag = option_bag.config_bag.copy() config_bag = option_bag.config_bag.copy()
config_bag.remove_validation() config_bag.unrestraint()
config_bag.context = tested_context config_bag.context = tested_context
soption_bag = option_bag.copy() soption_bag = option_bag.copy()
soption_bag.config_bag = config_bag soption_bag.config_bag = config_bag