properties are check now in getowner
authorEmmanuel Garette <egarette@cadoles.com>
Sat, 29 Mar 2014 19:31:56 +0000 (20:31 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Sat, 29 Mar 2014 19:31:56 +0000 (20:31 +0100)
get_modified_values works good with force_store_value

test/test_freeze.py
test/test_mandatory.py
test/test_option_owner.py
tiramisu/config.py
tiramisu/option.py
tiramisu/setting.py
tiramisu/value.py
translations/fr/tiramisu.po
translations/tiramisu.pot

index f279c47..362f26f 100644 (file)
@@ -142,18 +142,27 @@ def test_freeze_get_multi():
 def test_force_store_value():
     descr = make_description_freeze()
     conf = Config(descr)
-    assert conf.getowner(conf.unwrap_from_path('wantref')) == 'default'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
     conf.wantref
-    assert conf.getowner(conf.unwrap_from_path('wantref')) == 'user'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
+
+
+def test_force_store_value_no_requirement():
+    booloption = BoolOption('bool', 'Test boolean option', default=True)
+    try:
+        BoolOption('wantref', 'Test requires', default=False,
+                   requires=({'option': booloption, 'expected': True, 'action': 'force_store_value'},))
+    except ValueError:
+        pass
 
 
 def test_force_store_value_ro():
     descr = make_description_freeze()
     conf = Config(descr)
     conf.read_only()
-    assert conf.getowner(conf.unwrap_from_path('wantref')) == 'default'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
     conf.wantref
-    assert conf.getowner(conf.unwrap_from_path('wantref')) == 'user'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
 
 
 def test_force_store_value_hidden():
@@ -161,6 +170,60 @@ def test_force_store_value_hidden():
     conf = Config(descr)
     conf.cfgimpl_get_settings().setpermissive(('hidden',))
     conf.read_write()
-    assert conf.getowner(conf.unwrap_from_path('wantref2')) == 'default'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
     conf._getattr('wantref2', force_permissive=True)
-    assert conf.getowner(conf.unwrap_from_path('wantref2')) == 'user'
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref2': ('user', False)}
+
+
+def test_force_store_value_owner():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.getowner(conf.unwrap_from_path('wantref'))
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
+
+
+def test_force_store_value_owner_ro():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    conf.read_only()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.getowner(conf.unwrap_from_path('wantref'))
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
+
+
+def test_force_store_value_owner_hidden():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    conf.cfgimpl_get_settings().setpermissive(('hidden',))
+    conf.read_write()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.getowner(conf.unwrap_from_path('wantref2'), force_permissive=True)
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref2': ('user', False)}
+
+
+def test_force_store_value_modified():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.cfgimpl_get_values().get_modified_values()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}
+
+
+def test_force_store_value_modified_ro():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    conf.read_only()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.cfgimpl_get_values().get_modified_values()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}
+
+
+def test_force_store_value_modified_hidden():
+    descr = make_description_freeze()
+    conf = Config(descr)
+    conf.cfgimpl_get_settings().setpermissive(('hidden',))
+    conf.read_write()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
+    conf.cfgimpl_get_values().get_modified_values()
+    assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}
index 5b9878a..26c8e4b 100644 (file)
@@ -99,8 +99,8 @@ def test_mandatory_multi_none():
     descr = make_description()
     config = Config(descr)
     config.str3 = [None]
-    config.read_only()
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
+    config.read_only()
     prop = []
     try:
         config.str3
@@ -109,8 +109,8 @@ def test_mandatory_multi_none():
     assert 'mandatory' in prop
     config.read_write()
     config.str3 = ['yes', None]
-    config.read_only()
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
+    config.read_only()
     prop = []
     try:
         config.str3
@@ -123,8 +123,8 @@ def test_mandatory_multi_empty():
     descr = make_description()
     config = Config(descr)
     config.str3 = ['']
-    config.read_only()
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
+    config.read_only()
     prop = []
     try:
         config.str3
@@ -133,8 +133,8 @@ def test_mandatory_multi_empty():
     assert 'mandatory' in prop
     config.read_write()
     config.str3 = ['yes', '']
-    config.read_only()
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
+    config.read_only()
     prop = []
     try:
         config.str3
index d4c3f6b..1880bc4 100644 (file)
@@ -5,7 +5,7 @@ from tiramisu.setting import owners
 from tiramisu.config import Config
 from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
     StrOption, OptionDescription
-from tiramisu.error import ConfigError, ConstError
+from tiramisu.error import ConfigError, ConstError, PropertiesOptionError
 
 
 def make_description():
@@ -41,6 +41,14 @@ def test_default_owner():
     assert cfg.getowner(gcdummy) == owners.user
 
 
+def test_hidden_owner():
+    gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('hidden',))
+    descr = OptionDescription('tiramisu', '', [gcdummy])
+    cfg = Config(descr)
+    cfg.read_write()
+    raises(PropertiesOptionError, "cfg.getowner(gcdummy)")
+
+
 def test_addowner():
     gcdummy = BoolOption('dummy', 'dummy', default=False)
     descr = OptionDescription('tiramisu', '', [gcdummy])
index 2a882a1..8fc8e2d 100644 (file)
@@ -483,14 +483,15 @@ class _CommonConfig(SubConfig):
         "read write is a global config's setting, see `settings.py`"
         self.cfgimpl_get_settings().read_write()
 
-    def getowner(self, opt):
+    def getowner(self, opt, force_permissive=False):
         """convenience method to retrieve an option's owner
         from the config itself
         """
         if not isinstance(opt, Option) and not isinstance(opt, SymLinkOption):
             raise TypeError(_('opt in getowner must be an option not {0}'
                               '').format(type(opt)))
-        return self.cfgimpl_get_values().getowner(opt)
+        return self.cfgimpl_get_values().getowner(opt,
+                                                  force_permissive=force_permissive)
 
     def unwrap_from_path(self, path, force_permissive=False):
         """convenience method to extract and Option() object from the Config()
index eeab2f9..f4a53aa 100644 (file)
@@ -1461,6 +1461,10 @@ def validate_requires_arg(requires, name):
             raise ValueError(_("malformed requirements for option: {0}"
                                " require must have option, expected and"
                                " action keys").format(name))
+        if action == 'force_store_value':
+            raise ValueError(_("malformed requirements for option: {0}"
+                               " action cannot be force_store_value"
+                               ).format(name))
         inverse = require.get('inverse', False)
         if inverse not in [True, False]:
             raise ValueError(_('malformed requirements for option: {0}'
@@ -1543,10 +1547,10 @@ def validate_callback(callback, callback_params, type_):
                         if not isinstance(option, Option) and not \
                                 isinstance(option, SymLinkOption):
                             raise ValueError(_('{0}_params must have an option'
-                                            ' not a {0} for first argument'
-                                            ).format(type_, type(option)))
+                                               ' not a {0} for first argument'
+                                               ).format(type_, type(option)))
                         if force_permissive not in [True, False]:
                             raise ValueError(_('{0}_params must have a boolean'
-                                            ' not a {0} for second argument'
-                                            ).format(type_, type(
-                                                force_permissive)))
+                                               ' not a {0} for second argument'
+                                               ).format(type_, type(
+                                                   force_permissive)))
index 6ba84d7..8a7ae13 100644 (file)
@@ -365,7 +365,10 @@ class Settings(object):
             self._p_.reset_properties(_path)
         self._getcontext().cfgimpl_reset_cache()
 
-    def _getproperties(self, opt=None, path=None, is_apply_req=True):
+    def _getproperties(self, opt=None, path=None, _is_apply_req=True):
+        """
+        be careful, _is_apply_req doesn't copy properties
+        """
         if opt is None:
             props = copy(self._p_.getproperties(path, default_properties))
         else:
@@ -379,15 +382,16 @@ class Settings(object):
                 is_cached, props = self._p_.getcache(path, ntime)
                 if is_cached:
                     return copy(props)
-            props = copy(self._p_.getproperties(path, opt._properties))
-            if is_apply_req:
+            props = self._p_.getproperties(path, opt._properties)
+            if _is_apply_req:
+                props = copy(props)
                 props |= self.apply_requires(opt, path)
-            if 'cache' in self:
-                if 'expire' in self:
-                    if  ntime is None:
-                        ntime = int(time())
-                    ntime = ntime + expires_time
-                self._p_.setcache(path, copy(props), ntime)
+                if 'cache' in self:
+                    if 'expire' in self:
+                        if  ntime is None:
+                            ntime = int(time())
+                        ntime = ntime + expires_time
+                    self._p_.setcache(path, copy(props), ntime)
         return props
 
     def append(self, propname):
@@ -640,6 +644,15 @@ class Settings(object):
     def get_modified_permissives(self):
         return self._p_.get_modified_permissives()
 
+    def get_with_property(self, propname):
+        opts, paths = self._getcontext().cfgimpl_get_description(
+        )._cache_paths
+        for index in range(0, len(paths)):
+            opt = opts[index]
+            path = paths[index]
+            if propname in self._getproperties(opt, path, False):
+                yield (opt, path)
+
     def __getstate__(self):
         return {'_p_': self._p_, '_owner': str(self._owner)}
 
index d66f85d..e5c6111 100644 (file)
@@ -88,6 +88,11 @@ class Values(object):
         return value
 
     def get_modified_values(self):
+        context = self._getcontext()
+        if context._impl_descr is not None:
+            for opt, path in context.cfgimpl_get_settings(
+            ).get_with_property('force_store_value'):
+                self._getowner(opt, path, force_permissive=True)
         return self._p_.get_modified_values()
 
     def __contains__(self, opt):
@@ -196,7 +201,7 @@ class Values(object):
         # if value has callback and is not set
         # or frozen with force_default_on_freeze
         if opt.impl_has_callback() and (
-                self._is_default_owner(path) or
+                self._is_default_owner(opt, path, validate_properties=False) or
                 (is_frozen and 'force_default_on_freeze' in setting[opt])):
             lenmaster = None
             no_value_slave = False
@@ -241,7 +246,8 @@ class Values(object):
                 value = Multi(value, self.context, opt, path, validate=validate)
         if config_error is None and validate:
             opt.impl_validate(value, context, 'validator' in setting)
-        if config_error is None and self._is_default_owner(path) and \
+        if config_error is None and \
+                self._is_default_owner(opt, path, validate_properties=False) and \
                 'force_store_value' in setting[opt]:
             self.setitem(opt, value, path, is_write=False,
                          force_permissive=force_permissive)
@@ -303,23 +309,27 @@ class Values(object):
             value = list(value)
         self._p_.setvalue(path, value, owner)
 
-    def getowner(self, opt):
+    def getowner(self, opt, force_permissive=False):
         """
         retrieves the option's owner
 
         :param opt: the `option.Option` object
+        :param force_permissive: behaves as if the permissive property
+                                 was present
         :returns: a `setting.owners.Owner` object
         """
         if isinstance(opt, SymLinkOption):
             opt = opt._opt
         path = self._get_opt_path(opt)
-        return self._getowner(path)
+        return self._getowner(opt, path, force_permissive=force_permissive)
 
-    def _getowner(self, path):
-        owner = self._p_.getowner(path, owners.default)
+    def _getowner(self, opt, path, validate_properties=True, force_permissive=False):
         meta = self._getcontext().cfgimpl_get_meta()
+        if validate_properties:
+            self._getitem(opt, path, True, force_permissive, None, True)
+        owner = self._p_.getowner(path, owners.default)
         if owner is owners.default and meta is not None:
-            owner = meta.cfgimpl_get_values()._getowner(path)
+            owner = meta.cfgimpl_get_values()._getowner(opt, path)
         return owner
 
     def setowner(self, opt, owner):
@@ -333,25 +343,25 @@ class Values(object):
             raise TypeError(_("invalid generic owner {0}").format(str(owner)))
 
         path = self._get_opt_path(opt)
-        self._setowner(path, owner)
+        self._setowner(opt, path, owner)
 
-    def _setowner(self, path, owner):
-        if self._getowner(path) == owners.default:
+    def _setowner(self, opt, path, owner):
+        if self._getowner(opt, path) == owners.default:
             raise ConfigError(_('no value for {0} cannot change owner to {1}'
                                 '').format(path, owner))
         self._p_.setowner(path, owner)
 
-    def is_default_owner(self, opt):
+    def is_default_owner(self, opt, validate_properties=True):
         """
         :param config: *must* be only the **parent** config
                        (not the toplevel config)
         :return: boolean
         """
         path = self._get_opt_path(opt)
-        return self._is_default_owner(path)
+        return self._is_default_owner(opt, path, validate_properties)
 
-    def _is_default_owner(self, path):
-        return self._getowner(path) == owners.default
+    def _is_default_owner(self, opt, path, validate_properties=True):
+        return self._getowner(opt, path, validate_properties) == owners.default
 
     def reset_cache(self, only_expired):
         """
@@ -550,7 +560,8 @@ class Multi(list):
         if not force and self.opt.impl_get_multitype() == multitypes.master:
             for slave in self.opt.impl_get_master_slaves():
                 path = values._get_opt_path(slave)
-                if not values._is_default_owner(path):
+                if not values._is_default_owner(slave, path,
+                                                validate_properties=False):
                     if slave.impl_has_callback():
                         dvalue = values._getcallback_value(slave, index=index)
                     else:
@@ -631,7 +642,7 @@ class Multi(list):
             if self.opt.impl_get_multitype() == multitypes.master:
                 for slave in self.opt.impl_get_master_slaves():
                     values = context.cfgimpl_get_values()
-                    if not values.is_default_owner(slave):
+                    if not values.is_default_owner(slave, validate_properties=False):
                         #get multi without valid properties
                         values.getitem(slave, validate=False,
                                        validate_properties=False
index ab01ec6..eb14d72 100644 (file)
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Tiramisu\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-03-26 20:46+CET\n"
+"POT-Creation-Date: 2014-03-29 19:01+CET\n"
 "PO-Revision-Date: \n"
 "Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
 "Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
@@ -30,7 +30,7 @@ msgid "unknown group_type: {0}"
 msgstr "group_type inconnu: {0}"
 
 #: tiramisu/config.py:163 tiramisu/setting.py:334 tiramisu/value.py:55
-#: tiramisu/value.py:483
+#: tiramisu/value.py:500
 msgid "the context does not exist anymore"
 msgstr "le context n'existe plus"
 
@@ -63,27 +63,27 @@ msgstr "chemin imprévu {0}, devrait commencer par {1}"
 msgid "opt in getowner must be an option not {0}"
 msgstr "opt dans getowner doit être une option pas {0}"
 
-#: tiramisu/config.py:534
+#: tiramisu/config.py:535
 msgid "cannot serialize Config with MetaConfig"
 msgstr "impossible de sérialiser une Config avec une MetaConfig"
 
-#: tiramisu/config.py:548
+#: tiramisu/config.py:549
 msgid "this storage is not serialisable, could be a none persistent storage"
 msgstr "ce storage n'est sérialisable, devrait être une storage non persistant"
 
-#: tiramisu/config.py:611
+#: tiramisu/config.py:612
 msgid "metaconfig's children must be a list"
 msgstr "enfants d'une metaconfig doit être une liste"
 
-#: tiramisu/config.py:705
+#: tiramisu/config.py:706
 msgid "metaconfig's children should be config, not {0}"
 msgstr "enfants d'une metaconfig doit être une config, pas {0}"
 
-#: tiramisu/config.py:709
+#: tiramisu/config.py:710
 msgid "child has already a metaconfig's"
 msgstr "enfant a déjà une metaconfig"
 
-#: tiramisu/config.py:713
+#: tiramisu/config.py:714
 msgid "all config in metaconfig must have the same optiondescription"
 msgstr ""
 "toutes les configs d'une metaconfig doivent avoir la même optiondescription"
@@ -100,7 +100,7 @@ msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
 msgid "'{0}' ({1}) object attribute '{2}' is read-only"
 msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
 
-#: tiramisu/option.py:140 tiramisu/value.py:393
+#: tiramisu/option.py:140 tiramisu/value.py:410
 msgid "information's item not found: {0}"
 msgstr "aucune config spécifiée alors que c'est nécessaire"
 
@@ -420,77 +420,83 @@ msgstr ""
 "requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
 "option, expected et action"
 
-#: tiramisu/option.py:1466
+#: tiramisu/option.py:1465
+msgid ""
+"malformed requirements for option: {0} action cannot be force_store_value"
+msgstr ""
+"requirements mal formés pour l'option : {0} action ne peut pas être "
+"force_store_value"
+
+#: tiramisu/option.py:1470
 msgid "malformed requirements for option: {0} inverse must be boolean"
 msgstr ""
 "requirements mal formés pour l'option : {0} inverse doit être un booléen"
 
-#: tiramisu/option.py:1470
+#: tiramisu/option.py:1474
 msgid "malformed requirements for option: {0} transitive must be boolean"
 msgstr ""
 "requirements mal formés pour l'option : {0} transitive doit être booléen"
 
-#: tiramisu/option.py:1474
+#: tiramisu/option.py:1478
 msgid "malformed requirements for option: {0} same_action must be boolean"
 msgstr ""
 "requirements mal formés pour l'option : {0} same_action doit être un booléen"
 
-#: tiramisu/option.py:1478
+#: tiramisu/option.py:1482
 msgid "malformed requirements must be an option in option {0}"
 msgstr "requirements mal formés doit être une option dans l'option {0}"
 
-#: tiramisu/option.py:1481
+#: tiramisu/option.py:1485
 msgid "malformed requirements option {0} must not be a multi"
 msgstr "requirements mal formés l'option {0} ne doit pas être une multi"
 
-#: tiramisu/option.py:1487
+#: tiramisu/option.py:1491
 msgid ""
 "malformed requirements second argument must be valid for option {0}: {1}"
 msgstr ""
 "requirements mal formés deuxième argument doit être valide pour l'option "
 "{0} : {1}"
 
-#: tiramisu/option.py:1492
+#: tiramisu/option.py:1496
 msgid "inconsistency in action types for option: {0} action: {1}"
 msgstr "incohérence dans les types action pour l'option : {0} action {1}"
 
-#: tiramisu/option.py:1517
+#: tiramisu/option.py:1521
 msgid "{0} must be a function"
 msgstr "{0} doit être une fonction"
 
-#: tiramisu/option.py:1520
+#: tiramisu/option.py:1524
 msgid "{0}_params must be a dict"
 msgstr "{0}_params doit être un dict"
 
-#: tiramisu/option.py:1523
+#: tiramisu/option.py:1527
 msgid "{0}_params with key {1} mustn't have length different to 1"
 msgstr ""
 "{0}_params avec la clef {1} ne doit pas avoir une longueur différent de 1"
 
-#: tiramisu/option.py:1527
+#: tiramisu/option.py:1531
 msgid "{0}_params must be tuple for key \"{1}\""
 msgstr "{0}_params doit être un tuple pour la clef \"{1}\""
 
-#: tiramisu/option.py:1533
+#: tiramisu/option.py:1537
 msgid "{0}_params with length of tuple as 1 must only have None as first value"
 msgstr ""
 "{0}_params avec un tuple de longueur 1 doit seulement avoir None comme "
 "première valeur"
 
-#: tiramisu/option.py:1537
-#, fuzzy
+#: tiramisu/option.py:1541
 msgid "{0}_params must only have 1 or 2 as length"
 msgstr "{0}_params doit seulement avoir une longueur de 1 ou 2"
 
-#: tiramisu/option.py:1542
+#: tiramisu/option.py:1546
 msgid "validator not support tuple"
 msgstr "validator n'accepte pas de tuple"
 
-#: tiramisu/option.py:1545
+#: tiramisu/option.py:1549
 msgid "{0}_params must have an option not a {0} for first argument"
 msgstr "{0}_params doit avoir une option pas un {0} pour premier argument"
 
-#: tiramisu/option.py:1549
+#: tiramisu/option.py:1553
 msgid "{0}_params must have a boolean not a {0} for second argument"
 msgstr "{0}_params doit avoir un booléen pas un {0} pour second argument"
 
@@ -512,29 +518,29 @@ msgstr ""
 msgid "opt and all_properties must not be set together in reset"
 msgstr "opt et all_properties ne doit pas être renseigné ensemble dans reset"
 
-#: tiramisu/setting.py:373
+#: tiramisu/setting.py:376
 msgid "if opt is not None, path should not be None in _getproperties"
 msgstr ""
 "si opt n'est pas None, path devrait ne pas être à None dans _getproperties"
 
-#: tiramisu/setting.py:482
+#: tiramisu/setting.py:486
 msgid "cannot change the value for option {0} this option is frozen"
 msgstr ""
 "ne peut modifier la valeur de l'option {0} cette option n'est pas modifiable"
 
-#: tiramisu/setting.py:488
+#: tiramisu/setting.py:492
 msgid "trying to access to an option named: {0} with properties {1}"
 msgstr "tentative d'accès à une option nommée : {0} avec les propriétés {1}"
 
-#: tiramisu/setting.py:506
+#: tiramisu/setting.py:510
 msgid "permissive must be a tuple"
 msgstr "permissive doit être un tuple"
 
-#: tiramisu/setting.py:513 tiramisu/value.py:332
+#: tiramisu/setting.py:517 tiramisu/value.py:349
 msgid "invalid generic owner {0}"
 msgstr "invalide owner générique {0}"
 
-#: tiramisu/setting.py:601
+#: tiramisu/setting.py:605
 msgid ""
 "malformed requirements imbrication detected for option: '{0}' with "
 "requirement on: '{1}'"
@@ -542,7 +548,7 @@ msgstr ""
 "imbrication de requirements mal formés detectée pour l'option : '{0}' avec "
 "requirement sur : '{1}'"
 
-#: tiramisu/setting.py:612
+#: tiramisu/setting.py:616
 msgid "option '{0}' has requirement's property error: {1} {2}"
 msgstr "l'option '{0}' a une erreur de propriété pour le requirement : {1} {2}"
 
@@ -567,52 +573,52 @@ msgstr "session déjà utilisée"
 msgid "a dictionary cannot be persistent"
 msgstr "un espace de stockage dictionary ne peut être persistant"
 
-#: tiramisu/value.py:339
+#: tiramisu/value.py:356
 msgid "no value for {0} cannot change owner to {1}"
 msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
 
-#: tiramisu/value.py:421
+#: tiramisu/value.py:438
 msgid "can force cache only if cache is actived in config"
 msgstr ""
 "peut force la mise en cache seulement si le cache est activé dans la config"
 
-#: tiramisu/value.py:460
+#: tiramisu/value.py:477
 msgid "{0} is already a Multi "
 msgstr "{0} est déjà une Multi"
 
-#: tiramisu/value.py:496 tiramisu/value.py:560
+#: tiramisu/value.py:513 tiramisu/value.py:577
 msgid "invalid len for the slave: {0} which has {1} as master"
 msgstr "longueur invalide pour une esclave : {0} qui a {1} comme maître"
 
-#: tiramisu/value.py:532
+#: tiramisu/value.py:549
 msgid "cannot append a value on a multi option {0} which is a slave"
 msgstr "ne peut ajouter une valeur sur l'option multi {0} qui est une esclave"
 
-#: tiramisu/value.py:570
+#: tiramisu/value.py:587
 msgid "cannot sort multi option {0} if master or slave"
 msgstr "ne peut trier une option multi {0} pour une maître ou une esclave"
 
-#: tiramisu/value.py:574
+#: tiramisu/value.py:591
 msgid "cmp is not permitted in python v3 or greater"
 msgstr "cmp n'est pas permis en python v3 ou supérieure"
 
-#: tiramisu/value.py:583
+#: tiramisu/value.py:600
 msgid "cannot reverse multi option {0} if master or slave"
 msgstr "ne peut inverser une option multi {0} pour une maître ou une esclave"
 
-#: tiramisu/value.py:591
+#: tiramisu/value.py:608
 msgid "cannot insert multi option {0} if master or slave"
 msgstr "ne peut insérer une option multi {0} pour une maître ou une esclave"
 
-#: tiramisu/value.py:599
+#: tiramisu/value.py:616
 msgid "cannot extend multi option {0} if master or slave"
 msgstr "ne peut étendre une option multi {0} pour une maître ou une esclave"
 
-#: tiramisu/value.py:610
+#: tiramisu/value.py:627
 msgid "invalid value {0} for option {1}: {2}"
 msgstr "valeur invalide {0} pour l'option {1} : {2}"
 
-#: tiramisu/value.py:628
+#: tiramisu/value.py:645
 msgid "cannot pop a value on a multi option {0} which is a slave"
 msgstr "ne peut supprimer une valeur dans l'option multi {0} qui est esclave"
 
index 1bf9361..35ecafe 100644 (file)
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2014-03-26 20:46+CET\n"
+"POT-Creation-Date: 2014-03-29 19:01+CET\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -28,7 +28,7 @@ msgid "unknown group_type: {0}"
 msgstr ""
 
 #: tiramisu/config.py:163 tiramisu/setting.py:334 tiramisu/value.py:55
-#: tiramisu/value.py:483
+#: tiramisu/value.py:500
 msgid "the context does not exist anymore"
 msgstr ""
 
@@ -60,27 +60,27 @@ msgstr ""
 msgid "opt in getowner must be an option not {0}"
 msgstr ""
 
-#: tiramisu/config.py:534
+#: tiramisu/config.py:535
 msgid "cannot serialize Config with MetaConfig"
 msgstr ""
 
-#: tiramisu/config.py:548
+#: tiramisu/config.py:549
 msgid "this storage is not serialisable, could be a none persistent storage"
 msgstr ""
 
-#: tiramisu/config.py:611
+#: tiramisu/config.py:612
 msgid "metaconfig's children must be a list"
 msgstr ""
 
-#: tiramisu/config.py:705
+#: tiramisu/config.py:706
 msgid "metaconfig's children should be config, not {0}"
 msgstr ""
 
-#: tiramisu/config.py:709
+#: tiramisu/config.py:710
 msgid "child has already a metaconfig's"
 msgstr ""
 
-#: tiramisu/config.py:713
+#: tiramisu/config.py:714
 msgid "all config in metaconfig must have the same optiondescription"
 msgstr ""
 
@@ -96,7 +96,7 @@ msgstr ""
 msgid "'{0}' ({1}) object attribute '{2}' is read-only"
 msgstr ""
 
-#: tiramisu/option.py:140 tiramisu/value.py:393
+#: tiramisu/option.py:140 tiramisu/value.py:410
 msgid "information's item not found: {0}"
 msgstr ""
 
@@ -396,67 +396,71 @@ msgstr ""
 msgid "malformed requirements for option: {0} require must have option, expected and action keys"
 msgstr ""
 
-#: tiramisu/option.py:1466
-msgid "malformed requirements for option: {0} inverse must be boolean"
+#: tiramisu/option.py:1465
+msgid "malformed requirements for option: {0} action cannot be force_store_value"
 msgstr ""
 
 #: tiramisu/option.py:1470
-msgid "malformed requirements for option: {0} transitive must be boolean"
+msgid "malformed requirements for option: {0} inverse must be boolean"
 msgstr ""
 
 #: tiramisu/option.py:1474
-msgid "malformed requirements for option: {0} same_action must be boolean"
+msgid "malformed requirements for option: {0} transitive must be boolean"
 msgstr ""
 
 #: tiramisu/option.py:1478
+msgid "malformed requirements for option: {0} same_action must be boolean"
+msgstr ""
+
+#: tiramisu/option.py:1482
 msgid "malformed requirements must be an option in option {0}"
 msgstr ""
 
-#: tiramisu/option.py:1481
+#: tiramisu/option.py:1485
 msgid "malformed requirements option {0} must not be a multi"
 msgstr ""
 
-#: tiramisu/option.py:1487
+#: tiramisu/option.py:1491
 msgid "malformed requirements second argument must be valid for option {0}: {1}"
 msgstr ""
 
-#: tiramisu/option.py:1492
+#: tiramisu/option.py:1496
 msgid "inconsistency in action types for option: {0} action: {1}"
 msgstr ""
 
-#: tiramisu/option.py:1517
+#: tiramisu/option.py:1521
 msgid "{0} must be a function"
 msgstr ""
 
-#: tiramisu/option.py:1520
+#: tiramisu/option.py:1524
 msgid "{0}_params must be a dict"
 msgstr ""
 
-#: tiramisu/option.py:1523
+#: tiramisu/option.py:1527
 msgid "{0}_params with key {1} mustn't have length different to 1"
 msgstr ""
 
-#: tiramisu/option.py:1527
+#: tiramisu/option.py:1531
 msgid "{0}_params must be tuple for key \"{1}\""
 msgstr ""
 
-#: tiramisu/option.py:1533
+#: tiramisu/option.py:1537
 msgid "{0}_params with length of tuple as 1 must only have None as first value"
 msgstr ""
 
-#: tiramisu/option.py:1537
+#: tiramisu/option.py:1541
 msgid "{0}_params must only have 1 or 2 as length"
 msgstr ""
 
-#: tiramisu/option.py:1542
+#: tiramisu/option.py:1546
 msgid "validator not support tuple"
 msgstr ""
 
-#: tiramisu/option.py:1545
+#: tiramisu/option.py:1549
 msgid "{0}_params must have an option not a {0} for first argument"
 msgstr ""
 
-#: tiramisu/option.py:1549
+#: tiramisu/option.py:1553
 msgid "{0}_params must have a boolean not a {0} for second argument"
 msgstr ""
 
@@ -476,31 +480,31 @@ msgstr ""
 msgid "opt and all_properties must not be set together in reset"
 msgstr ""
 
-#: tiramisu/setting.py:373
+#: tiramisu/setting.py:376
 msgid "if opt is not None, path should not be None in _getproperties"
 msgstr ""
 
-#: tiramisu/setting.py:482
+#: tiramisu/setting.py:486
 msgid "cannot change the value for option {0} this option is frozen"
 msgstr ""
 
-#: tiramisu/setting.py:488
+#: tiramisu/setting.py:492
 msgid "trying to access to an option named: {0} with properties {1}"
 msgstr ""
 
-#: tiramisu/setting.py:506
+#: tiramisu/setting.py:510
 msgid "permissive must be a tuple"
 msgstr ""
 
-#: tiramisu/setting.py:513 tiramisu/value.py:332
+#: tiramisu/setting.py:517 tiramisu/value.py:349
 msgid "invalid generic owner {0}"
 msgstr ""
 
-#: tiramisu/setting.py:601
+#: tiramisu/setting.py:605
 msgid "malformed requirements imbrication detected for option: '{0}' with requirement on: '{1}'"
 msgstr ""
 
-#: tiramisu/setting.py:612
+#: tiramisu/setting.py:616
 msgid "option '{0}' has requirement's property error: {1} {2}"
 msgstr ""
 
@@ -524,51 +528,51 @@ msgstr ""
 msgid "a dictionary cannot be persistent"
 msgstr ""
 
-#: tiramisu/value.py:339
+#: tiramisu/value.py:356
 msgid "no value for {0} cannot change owner to {1}"
 msgstr ""
 
-#: tiramisu/value.py:421
+#: tiramisu/value.py:438
 msgid "can force cache only if cache is actived in config"
 msgstr ""
 
-#: tiramisu/value.py:460
+#: tiramisu/value.py:477
 msgid "{0} is already a Multi "
 msgstr ""
 
-#: tiramisu/value.py:496 tiramisu/value.py:560
+#: tiramisu/value.py:513 tiramisu/value.py:577
 msgid "invalid len for the slave: {0} which has {1} as master"
 msgstr ""
 
-#: tiramisu/value.py:532
+#: tiramisu/value.py:549
 msgid "cannot append a value on a multi option {0} which is a slave"
 msgstr ""
 
-#: tiramisu/value.py:570
+#: tiramisu/value.py:587
 msgid "cannot sort multi option {0} if master or slave"
 msgstr ""
 
-#: tiramisu/value.py:574
+#: tiramisu/value.py:591
 msgid "cmp is not permitted in python v3 or greater"
 msgstr ""
 
-#: tiramisu/value.py:583
+#: tiramisu/value.py:600
 msgid "cannot reverse multi option {0} if master or slave"
 msgstr ""
 
-#: tiramisu/value.py:591
+#: tiramisu/value.py:608
 msgid "cannot insert multi option {0} if master or slave"
 msgstr ""
 
-#: tiramisu/value.py:599
+#: tiramisu/value.py:616
 msgid "cannot extend multi option {0} if master or slave"
 msgstr ""
 
-#: tiramisu/value.py:610
+#: tiramisu/value.py:627
 msgid "invalid value {0} for option {1}: {2}"
 msgstr ""
 
-#: tiramisu/value.py:628
+#: tiramisu/value.py:645
 msgid "cannot pop a value on a multi option {0} which is a slave"
 msgstr ""