force_store_value is rebuild if needed
authorEmmanuel Garette <egarette@cadoles.com>
Thu, 22 Sep 2016 06:27:18 +0000 (08:27 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Thu, 22 Sep 2016 06:27:18 +0000 (08:27 +0200)
ChangeLog
test/test_config.py
test/test_duplicate_config.py
test/test_metaconfig.py
tiramisu/config.py
tiramisu/option/optiondescription.py
tiramisu/storage/dictionary/option.py

index e3c85ad..4f15433 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+Thu Sep 22 08:25:33 2016 +0200 Emmanuel Garette <egarette@cadoles.com>
+       * force_store_value is rebuild if needed
+
 Mon Mar  7 16:10:30 2016 +0200 Emmanuel Garette <egarette@cadoles.com>
        * force_store_value is now used directly when configuration is loaded
        * add force_permissive to Values.is_default_owner
index 8c7e332..9dfb809 100644 (file)
@@ -376,3 +376,15 @@ def test_config_od_function():
     except AttributeError as err:
         assert str(err) == _('unknown Option {0} in OptionDescription {1}'
                              '').format('impl_get_opt_by_path', descr.impl_getname())
+
+
+def test_config_subconfig():
+    i1 = IntOption('i1', '')
+    i2 = IntOption('i2', '', default=1)
+    i3 = IntOption('i3', '')
+    i4 = IntOption('i4', '', default=2)
+    od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2, name='conf1')
+    conf1
+    raises(ConfigError, "conf2 = Config(od1, name='conf2')")
index c6e9a6d..ce3dd3a 100644 (file)
@@ -25,6 +25,7 @@ def make_description():
     adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True)
     time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur',
                              ('Paris', 'Londres'), 'Paris')
+    wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',))
 
     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé")
     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
@@ -36,7 +37,7 @@ def make_description():
     general = OptionDescription('general', '', [numero_etab, nom_machine,
                                 nombre_interfaces, activer_proxy_client,
                                 mode_conteneur_actif, mode_conteneur_actif2,
-                                adresse_serveur_ntp, time_zone])
+                                adresse_serveur_ntp, time_zone, wantref_option])
     general.impl_set_group_type(groups.family)
     new = OptionDescription('new', '', [], properties=('hidden',))
     new.impl_set_group_type(groups.family)
@@ -54,3 +55,14 @@ def test_duplicate():
     raises(AssertionError, "_diff_conf(cfg, ncfg)")
     ncfg.creole.general.numero_etab = 'oui'
     _diff_conf(cfg, ncfg)
+
+
+def test_duplicate_force_store_value():
+    descr = make_description()
+    conf = Config(descr)
+    conf2 = Config(descr)
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'creole.general.wantref': ('forced', False)}
+    assert conf2.cfgimpl_get_values()._p_.get_modified_values() == {'creole.general.wantref': ('forced', False)}
+    conf.creole.general.wantref = True
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'creole.general.wantref': ('user', True)}
+    assert conf2.cfgimpl_get_values()._p_.get_modified_values() == {'creole.general.wantref': ('forced', False)}
index e53b4dc..f14e4d1 100644 (file)
@@ -231,10 +231,11 @@ def test_meta_unconsistent():
     i4 = IntOption('i4', '', default=2)
     od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
     od2 = OptionDescription('od2', '', [od1])
+    od3 = OptionDescription('od3', '', [od1])
     conf1 = Config(od2, name='conf1')
     conf2 = Config(od2, name='conf2')
     conf3 = Config(od2, name='conf3')
-    conf4 = Config(od1, name='conf4')
+    conf4 = Config(od3, name='conf4')
     conf3, conf4
     meta = MetaConfig([conf1, conf2])
     meta.cfgimpl_get_settings().setowner(owners.meta)
index 6cc8e4d..8cf061d 100644 (file)
@@ -548,6 +548,7 @@ class _CommonConfig(SubConfig):
         if not descr.impl_already_build_caches():
             descr.impl_build_cache_option()
             descr.impl_build_cache(self)
+        descr.impl_build_force_store_values(self)
 
     def read_only(self):
         "read only is a global config's setting, see `settings.py`"
@@ -697,7 +698,8 @@ class Config(_CommonConfig):
         self._impl_meta = None
         #undocumented option used only in test script
         self._impl_test = False
-        self._impl_build_all_caches()
+        if force_settings is None or force_values is None:
+            self._impl_build_all_caches()
         self._impl_name = name
 
     def cfgimpl_reset_cache(self,
index 1dda5b5..6edc458 100644 (file)
@@ -102,6 +102,9 @@ class OptionDescription(BaseOption, StorageOptionDescription):
         """validate duplicate option and set option has readonly option
         """
         if cache_option is None:
+            if self.impl_is_readonly():
+                raise ConfigError(_('option description seems to be part of an other '
+                                    'config'))
             init = True
             _consistencies = {}
             cache_option = []
@@ -189,24 +192,29 @@ class OptionDescription(BaseOption, StorageOptionDescription):
                                             'which is not in Config').format(
                                                 opt.impl_getname()))
                     self._cache_consistencies[opt] = tuple(cons)
+            self._cache_force_store_values = force_store_values
             self._set_readonly(False)
-            for subpath, option in force_store_values:
-                value = config.cfgimpl_get_values()._get_cached_value(option,
-                                                                      path=subpath,
-                                                                      validate=False,
-                                                                      trusted_cached_properties=False,
-                                                                      validate_properties=True)
-                if option.impl_is_master_slaves('slave'):
-                    # problem with index
-                    raise ConfigError(_('a slave ({0}) cannot have '
-                                        'force_store_value property').format(subpath))
-                if option._is_subdyn():
-                    raise ConfigError(_('a dynoption ({0}) cannot have '
-                                        'force_store_value property').format(subpath))
-                config._impl_values._p_.setvalue(subpath, value,
-                                                 owners.forced, None, session)
             del(session)
 
+
+    def impl_build_force_store_values(self, config):
+        session = config._impl_values._p_.getsession()
+        for subpath, option in self._cache_force_store_values:
+            value = config.cfgimpl_get_values()._get_cached_value(option,
+                                                                  path=subpath,
+                                                                  validate=False,
+                                                                  trusted_cached_properties=False,
+                                                                  validate_properties=True)
+            if option.impl_is_master_slaves('slave'):
+                # problem with index
+                raise ConfigError(_('a slave ({0}) cannot have '
+                                    'force_store_value property').format(subpath))
+            if option._is_subdyn():
+                raise ConfigError(_('a dynoption ({0}) cannot have '
+                                    'force_store_value property').format(subpath))
+            config._impl_values._p_.setvalue(subpath, value,
+                                             owners.forced, None, session)
+
     # ____________________________________________________________
     def impl_set_group_type(self, group_type):
         """sets a given group object to an OptionDescription
index 57c713c..481a1f4 100644 (file)
@@ -363,7 +363,7 @@ class StorageBase(object):
 
 class StorageOptionDescription(StorageBase):
     __slots__ = ('_children', '_cache_paths', '_cache_consistencies',
-                 '_group_type', '_state_group_type')
+                 '_group_type', '_state_group_type', '_cache_force_store_values')
 
     def __init__(self, name, multi, warnings_only, doc, extra):
         super(StorageOptionDescription, self).__init__(name, multi,