consistency "not_equal" works now with multi
authorEmmanuel Garette <egarette@cadoles.com>
Wed, 16 Nov 2016 21:31:42 +0000 (22:31 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Wed, 16 Nov 2016 21:31:42 +0000 (22:31 +0100)
ChangeLog
test/test_option_consistency.py
test/test_option_setting.py
tiramisu/option/baseoption.py
tiramisu/option/optiondescription.py
translations/fr/tiramisu.po
translations/tiramisu.pot

index 3c2e8af..134251e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+Wed Nov 16 22:30:12 2016 +0200 Emmanuel Garette <egarette@cadoles.com>
+       * consistency "not_equal" works now with multi
+
 Wed Oct 12 21:55:53 2016 +0200 Emmanuel Garette <egarette@cadoles.com>
        * consistency is now check "not_equal" if one option has
        PropertiesOptionError
index f83e135..01e9c90 100644 (file)
@@ -217,7 +217,7 @@ def test_consistency_not_equal_default_submulti():
     raises(ConfigError, "a.impl_add_consistency('not_equal', b)")
 
 
-def test_consistency_not_equal_multi():
+def test_consistency_not_equal_masterslave():
     a = IntOption('a', '', multi=True)
     b = IntOption('b', '', multi=True)
     od = OptionDescription('a', '', [a, b])
@@ -233,7 +233,7 @@ def test_consistency_not_equal_multi():
     c.b = [2]
 
 
-def test_consistency_not_equal_multi_default():
+def test_consistency_not_equal_masterslaves_default():
     a = IntOption('a', '', multi=True)
     b = IntOption('b', '', multi=True, default_multi=1)
     od = OptionDescription('a', '', [a, b])
@@ -247,6 +247,46 @@ def test_consistency_not_equal_multi_default():
     del(c.a)
 
 
+def test_consistency_not_equal_multi():
+    a = IntOption('a', '', multi=True)
+    b = IntOption('b', '', multi=True)
+    od = OptionDescription('a', '', [a, b])
+    a.impl_add_consistency('not_equal', b)
+    c = Config(od)
+    assert c.a == []
+    assert c.b == []
+    c.a = [1]
+    del(c.a)
+    c.a = [1]
+    raises(ValueError, "c.b = [1]")
+    c.b = [2]
+    raises(ValueError, "c.b = [2, 1]")
+    raises(ValueError, "c.b.append(1)")
+    c.b.append(3)
+    raises(ValueError, "c.b.append(3)")
+    raises(ValueError, "c.a.append(3)")
+    raises(ValueError, "c.a.append(3)")
+
+
+def test_consistency_not_equal_multi_default():
+    a = IntOption('a', '', multi=True, default=[1])
+    b = IntOption('b', '', multi=True, default=[1, 2])
+    od = OptionDescription('a', '', [a, b])
+    raises(ValueError, "a.impl_add_consistency('not_equal', b)")
+
+
+def test_consistency_not_equal_multi_default_modif():
+    a = IntOption('a', '', multi=True)
+    b = IntOption('b', '', multi=True, default=[1, 2])
+    od = OptionDescription('a', '', [a, b])
+    a.impl_add_consistency('not_equal', b)
+    c = Config(od)
+    assert c.a == []
+    assert c.b == [1, 2]
+    raises(ValueError, 'c.a.append(1)')
+    raises(ValueError, 'c.b.append(1)')
+
+
 def test_consistency_default():
     a = IntOption('a', '', 1)
     b = IntOption('b', '', 1)
index 02544e2..fc0ebd2 100644 (file)
@@ -519,7 +519,14 @@ def test_pprint():
     except Exception, err:
         pass
 
-    assert str(err) == msg_error.format('option', 'Test string option', 'properties', display_list(['disabled (' + display_list([msg_is.format('string2', 'string'), msg_is.format('Test int option', '1')]) + ')', 'hidden (' + msg_is_not.format('Test int option', display_list([2, 3, 4], 'or')) + ')']))
+    list_disabled_1 = 'disabled (' + display_list([msg_is.format('string2', 'string'), msg_is.format('Test int option', '1')]) + ')'
+    list_disabled_2 = 'disabled (' + display_list([msg_is.format('Test int option', '1'), msg_is.format('string2', 'string')]) + ')'
+    list_hidden = 'hidden (' + msg_is_not.format('Test int option', display_list([2, 3, 4], 'or')) + ')'
+    comp1 = str(err) == msg_error.format('option', 'Test string option', 'properties', display_list([list_disabled_1, list_hidden]))
+    comp2 = str(err) == msg_error.format('option', 'Test string option', 'properties', display_list([list_disabled_2, list_hidden]))
+    comp3 = str(err) == msg_error.format('option', 'Test string option', 'properties', display_list([list_hidden, list_disabled_1]))
+    comp4 = str(err) == msg_error.format('option', 'Test string option', 'properties', display_list([list_hidden, list_disabled_2]))
+    assert comp1 or comp2 or comp3 or comp4
 
     try:
         config.options.val2
@@ -532,8 +539,23 @@ def test_pprint():
         config.val3
     except Exception, err:
         pass
-
-    assert str(err) == msg_error.format('option', 'val3', 'property', 'hidden (' + display_list([msg_is.format('string2', 'string'), msg_is.format('Test int option', 1), msg_is_not.format('Test int option', display_list([2, 3, 4], 'or'))]) + ')')
+    msg_1 = msg_is.format('string2', 'string')
+    msg_2 = msg_is.format('Test int option', 1)
+    msg_3 = msg_is_not.format('Test int option', display_list([2, 3, 4], 'or'))
+
+    list_hidden = 'hidden (' + display_list([msg_1, msg_2, msg_3]) + ')'
+    comp1 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    list_hidden = 'hidden (' + display_list([msg_1, msg_3, msg_2]) + ')'
+    comp2 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    list_hidden = 'hidden (' + display_list([msg_2, msg_1, msg_3]) + ')'
+    comp3 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    list_hidden = 'hidden (' + display_list([msg_2, msg_3, msg_1]) + ')'
+    comp4 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    list_hidden = 'hidden (' + display_list([msg_3, msg_1, msg_2]) + ')'
+    comp5 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    list_hidden = 'hidden (' + display_list([msg_3, msg_2, msg_1]) + ')'
+    comp6 = str(err) == msg_error.format('option', 'val3', 'property', list_hidden)
+    assert comp1 or comp2 or comp3 or comp4 or comp5 or comp6
 
     try:
         config.string
index c97928d..fa92fdb 100644 (file)
@@ -32,12 +32,17 @@ from ..storage import get_storages_option
 from . import MasterSlaves
 
 
+if sys.version_info[0] >= 3:  # pragma: optional cover
+    xrange = range
+
+
 StorageBase = get_storages_option('base')
 submulti = 2
 name_regexp = re.compile(r'^[a-z][a-zA-Z\d\-_]*$')
 forbidden_names = frozenset(['iter_all', 'iter_group', 'find', 'find_first',
                              'make_dict', 'unwrap_from_path', 'read_only',
                              'read_write', 'getowner', 'set_contexts'])
+allowed_const_list = ['_cons_not_equal']
 
 
 def valid_name(name):
@@ -382,7 +387,7 @@ class Option(OnlyOption):
     _empty = ''
 
     def _launch_consistency(self, current_opt, func, option, value, context,
-                            index, submulti_index, all_cons_opts, warnings_only,
+                            index, submulti_index, opts, warnings_only,
                             transitive):
         """Launch consistency now
 
@@ -396,8 +401,8 @@ class Option(OnlyOption):
         :param index: only for multi option, consistency should be launch for
                       specified index
         :type index: `int`
-        :param all_cons_opts: all options concerne by this consistency
-        :type all_cons_opts: `list` of `tiramisu.option.Option`
+        :param opts: all options concerne by this consistency
+        :type opts: `list` of `tiramisu.option.Option`
         :param warnings_only: specific raise error for warning
         :type warnings_only: `boolean`
         :param transitive: propertyerror is transitive
@@ -407,14 +412,16 @@ class Option(OnlyOption):
             descr = context.cfgimpl_get_description()
 
         all_cons_vals = []
+        all_cons_opts = []
         val_consistencies = True
-        for opt in all_cons_opts:
-
-            if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
-                    option == opt:
+        for opt in opts:
+            is_multi = opt.impl_is_multi() and not opt.impl_is_master_slaves()
+            if not is_multi and ((isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
+                    option == opt):
                 # option is current option
                 # we have already value, so use it
                 all_cons_vals.append(value)
+                all_cons_opts.append(opt)
             else:
                 #if context, calculate value, otherwise get default value
                 path = None
@@ -423,8 +430,12 @@ class Option(OnlyOption):
                         path = opt.impl_getpath(context)
                     else:
                         path = descr.impl_get_path_by_opt(opt)
+                    if is_multi:
+                        _index = None
+                    else:
+                        _index = index
                     opt_value = context.getattr(path, validate=False,
-                                                index=index,
+                                                index=_index,
                                                 force_permissive=True,
                                                 returns_raise=True)
                     if isinstance(opt_value, Exception):
@@ -445,7 +456,13 @@ class Option(OnlyOption):
                 if self.impl_is_multi() and index is None:
                     # only check propertyerror for master/slaves is transitive
                     val_consistencies = False
-                all_cons_vals.append(opt_value)
+                if is_multi and isinstance(opt_value, list):
+                    all_cons_vals.extend(opt_value)
+                    for len_ in xrange(len(opt_value)):
+                        all_cons_opts.append(opt)
+                else:
+                    all_cons_vals.append(opt_value)
+                    all_cons_opts.append(opt)
 
         if val_consistencies:
             return getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only)
@@ -750,17 +767,21 @@ class Option(OnlyOption):
                     for opt_ in [opts[idx_inf], opts[idx_inf + idx_sup + 1]]:
                         if opt_ == current_opt:
                             is_current = True
-                        else:
-                            equal.add('"{}"'.format(opt_.impl_get_display_name()))
+                        equal.add('"{}"'.format(opt_.impl_get_display_name()))
         if equal:
             if debug:
                 log.debug(_('_cons_not_equal: {} are not different').format(display_list(list(equal))))
             if is_current:
-                if warnings_only:
-                    msg = _('should be different from the value of {}')
+                equal.remove('"' + current_opt.impl_get_display_name() + '"')
+                if len(equal) == 0:
+                    msg = _('this value is already present')
+                    return ValueError(msg)
                 else:
-                    msg = _('must be different from the value of {}')
-                return ValueError(msg.format(display_list(list(equal))))
+                    if warnings_only:
+                        msg = _('should be different from the value of {}')
+                    else:
+                        msg = _('must be different from the value of {}')
+                    return ValueError(msg.format(display_list(list(equal))))
             else:
                 if warnings_only:
                     msg = _('value for {} should be different')
index 339416a..56a86e0 100644 (file)
@@ -24,7 +24,7 @@ import re
 
 from ..i18n import _
 from ..setting import groups, undefined, owners  # , log
-from .baseoption import BaseOption, SymLinkOption, Option
+from .baseoption import BaseOption, SymLinkOption, Option, allowed_const_list
 from . import MasterSlaves
 from ..error import ConfigError, ConflictError
 from ..storage import get_storages_option
@@ -131,22 +131,22 @@ class OptionDescription(BaseOption, StorageOptionDescription):
                     force_store_values.append((subpath, option))
                 for func, all_cons_opts, params in option._get_consistencies():
                     option._valid_consistencies(all_cons_opts[1:], init=False)
-                    if is_multi:
+                    if func not in allowed_const_list and is_multi:
                         is_slave = option.impl_is_master_slaves()
                         if not is_slave:
-                            raise ValueError(_('malformed consistency option {0} '
+                            raise ValueError(_('malformed consistency option "{0}" '
                                                'must be a master/slaves').format(
                                                    option.impl_getname()))
                         masterslaves = option.impl_get_master_slaves()
                     for opt in all_cons_opts:
-                        if is_multi:
+                        if func not in allowed_const_list and is_multi:
                             if not opt.impl_is_master_slaves():
-                                raise ValueError(_('malformed consistency option {0} '
-                                                   'must not be a multi for {1}').format(
+                                raise ValueError(_('malformed consistency option "{0}" '
+                                                   'must not be a multi for "{1}"').format(
                                                        option.impl_getname(), opt.impl_getname()))
                             elif masterslaves != opt.impl_get_master_slaves():
-                                raise ValueError(_('malformed consistency option {0} '
-                                                   'must be in same master/slaves for {1}').format(
+                                raise ValueError(_('malformed consistency option "{0}" '
+                                                   'must be in same master/slaves for "{1}"').format(
                                                        option.impl_getname(), opt.impl_getname()))
                         _consistencies.setdefault(opt,
                                                   []).append((func,
index 8d890a1..4554712 100644 (file)
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Tiramisu\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-11-14 21:31+0100\n"
+"POT-Creation-Date: 2016-11-16 22:29+0100\n"
 "PO-Revision-Date: \n"
 "Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
 "Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
@@ -128,71 +128,71 @@ msgstr ""
 msgid " {} "
 msgstr " {} "
 
-#: tiramisu/error.py:49
+#: tiramisu/error.py:52
 msgid "property"
 msgstr "propriété"
 
-#: tiramisu/error.py:51
+#: tiramisu/error.py:54
 msgid "properties"
 msgstr "propriétés"
 
-#: tiramisu/error.py:53 tiramisu/setting.py:517
+#: tiramisu/error.py:56 tiramisu/setting.py:517
 msgid "cannot access to {0} \"{1}\" because has {2} {3}"
 msgstr "ne peut accéder à l'{0} \"{1}\" a cause de {2} {3}"
 
-#: tiramisu/option/baseoption.py:58
+#: tiramisu/option/baseoption.py:63
 msgid "{0} must be a function"
 msgstr "{0} doit être une fonction"
 
-#: tiramisu/option/baseoption.py:61
+#: tiramisu/option/baseoption.py:66
 msgid "{0}_params must be a dict"
 msgstr "{0}_params doit être un dict"
 
-#: tiramisu/option/baseoption.py:64
+#: tiramisu/option/baseoption.py:69
 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/baseoption.py:68
+#: tiramisu/option/baseoption.py:73
 msgid "{0}_params must be tuple for key \"{1}\""
 msgstr "{0}_params doit être un tuple pour la clef \"{1}\""
 
-#: tiramisu/option/baseoption.py:74
+#: tiramisu/option/baseoption.py:79
 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/baseoption.py:78
+#: tiramisu/option/baseoption.py:83
 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/baseoption.py:84
+#: tiramisu/option/baseoption.py:89
 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/baseoption.py:88
+#: tiramisu/option/baseoption.py:93
 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"
 
-#: tiramisu/option/baseoption.py:105
+#: tiramisu/option/baseoption.py:110
 msgid "invalid name: {0} for option"
 msgstr "nom invalide : {0} pour l'option"
 
-#: tiramisu/option/baseoption.py:107
+#: tiramisu/option/baseoption.py:112
 msgid "default_multi is set whereas multi is False in option: {0}"
 msgstr ""
 "default_multi est spécifié alors que multi est à False pour l'option : {0}"
 
-#: tiramisu/option/baseoption.py:119
+#: tiramisu/option/baseoption.py:124
 msgid "invalid multi value"
 msgstr "valeur multiple invalide"
 
-#: tiramisu/option/baseoption.py:129
+#: tiramisu/option/baseoption.py:134
 msgid "invalid properties type {0} for {1}, must be a tuple"
 msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
 
-#: tiramisu/option/baseoption.py:168
+#: tiramisu/option/baseoption.py:173
 msgid ""
 "params defined for a callback function but no callback defined yet for "
 "option {0}"
@@ -200,131 +200,137 @@ msgstr ""
 "params définis pour une fonction callback mais par de callback encore "
 "définis pour l'option {0}"
 
-#: tiramisu/option/baseoption.py:173
+#: tiramisu/option/baseoption.py:178
 msgid "a callback is already set for option {0}, cannot set another one's"
 msgstr ""
 "un callback est en lecture seul pour l'option {0}, ne peut en placer une "
 "autre"
 
-#: tiramisu/option/baseoption.py:257
+#: tiramisu/option/baseoption.py:262
 msgid "cannot serialize Option, only in OptionDescription"
 msgstr "ne peut serialiser une Option, seulement via une OptionDescription"
 
-#: tiramisu/option/baseoption.py:338 tiramisu/storage/dictionary/option.py:119
+#: tiramisu/option/baseoption.py:343 tiramisu/storage/dictionary/option.py:119
 msgid "'{0}' ({1}) object attribute '{2}' is read-only"
 msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
 
-#: tiramisu/option/baseoption.py:359
+#: tiramisu/option/baseoption.py:364
 msgid "invalid string"
 msgstr "invalide caractère"
 
-#: tiramisu/option/baseoption.py:362
+#: tiramisu/option/baseoption.py:367
 msgid "invalid unicode or string"
 msgstr "invalide unicode ou string"
 
-#: tiramisu/option/baseoption.py:515 tiramisu/option/baseoption.py:560
+#: tiramisu/option/baseoption.py:532 tiramisu/option/baseoption.py:577
 msgid "\"{0}\" is an invalid {1} for \"{2}\", {3}"
-msgstr "\"{0}\" est une {1} invalide pour \"{2}\", {3}"
+msgstr "\"{0}\" est une option de type {1} invalide pour \"{2}\", {3}"
 
-#: tiramisu/option/baseoption.py:519 tiramisu/option/baseoption.py:564
+#: tiramisu/option/baseoption.py:536 tiramisu/option/baseoption.py:581
 msgid "\"{0}\" is an invalid {1} for \"{2}\""
-msgstr "\"{0}\" est une {1} invalide pour \"{2}\""
+msgstr "\"{0}\" est une option de type {1} invalide pour \"{2}\""
 
-#: tiramisu/option/baseoption.py:531
+#: tiramisu/option/baseoption.py:548
 msgid "do_validation for {0}: error in value"
 msgstr "do_validation for {0} : erreur dans un la valeur"
 
-#: tiramisu/option/baseoption.py:550
+#: tiramisu/option/baseoption.py:567
 msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\", {3}"
-msgstr "attention, \"{0}\" peut être une {1} invalide pour \"{2}\", {3}"
+msgstr ""
+"attention, \"{0}\" peut être une option de type {1} invalide pour \"{2}\", "
+"{3}"
 
-#: tiramisu/option/baseoption.py:580 tiramisu/option/baseoption.py:590
+#: tiramisu/option/baseoption.py:597 tiramisu/option/baseoption.py:607
 msgid "invalid value {0} for option {1} which must be a list"
 msgstr "valeur invalide pour l'option {0} : {1} laquelle doit être une liste"
 
-#: tiramisu/option/baseoption.py:596
+#: tiramisu/option/baseoption.py:613
 msgid "invalid value {0} for option {1} which must be a list of list"
 msgstr ""
 "valeur invalide pour l'option {0} : {1} laquelle doit être une liste de liste"
 
-#: tiramisu/option/baseoption.py:647 tiramisu/option/baseoption.py:651
+#: tiramisu/option/baseoption.py:664 tiramisu/option/baseoption.py:668
 msgid "cannot add consistency with submulti option"
 msgstr "ne peut ajouter de test de consistence a une option submulti"
 
-#: tiramisu/option/baseoption.py:653
+#: tiramisu/option/baseoption.py:670
 msgid "consistency must be set with an option"
 msgstr "consistency doit être configuré avec une option"
 
-#: tiramisu/option/baseoption.py:656 tiramisu/option/baseoption.py:663
+#: tiramisu/option/baseoption.py:673 tiramisu/option/baseoption.py:680
 msgid ""
 "almost one option in consistency is in a dynoptiondescription but not all"
 msgstr ""
 "au moins une option dans le test de consistance est dans une "
 "dynoptiondescription mais pas toutes"
 
-#: tiramisu/option/baseoption.py:659
+#: tiramisu/option/baseoption.py:676
 msgid "option in consistency must be in same dynoptiondescription"
 msgstr ""
 "option dans une consistency doit être dans le même dynoptiondescription"
 
-#: tiramisu/option/baseoption.py:666
+#: tiramisu/option/baseoption.py:683
 msgid "cannot add consistency with itself"
 msgstr "ne peut ajouter une consistency avec lui même"
 
-#: tiramisu/option/baseoption.py:668
+#: tiramisu/option/baseoption.py:685
 msgid "every options in consistency must be multi or none"
 msgstr ""
 "toutes les options d'une consistency doivent être multi ou ne pas l'être"
 
-#: tiramisu/option/baseoption.py:685
+#: tiramisu/option/baseoption.py:702
 msgid "'{0}' ({1}) cannot add consistency, option is read-only"
 msgstr ""
 "'{0}' ({1}) ne peut ajouter de consistency, l'option est en lecture seul"
 
-#: tiramisu/option/baseoption.py:692
+#: tiramisu/option/baseoption.py:709
 msgid "consistency {0} not available for this option"
 msgstr "consistency {0} non valable pour cette option"
 
-#: tiramisu/option/baseoption.py:696
+#: tiramisu/option/baseoption.py:713
 msgid "unknow parameter {0} in consistency"
 msgstr "paramètre inconnu {0} dans un test de consistance"
 
-#: tiramisu/option/baseoption.py:757
+#: tiramisu/option/baseoption.py:773
 msgid "_cons_not_equal: {} are not different"
 msgstr "_cons_not_equal: {} sont différents"
 
-#: tiramisu/option/baseoption.py:760
+#: tiramisu/option/baseoption.py:777
+msgid "this value is already present"
+msgstr "cette valeur est déjà présente"
+
+#: tiramisu/option/baseoption.py:781
 msgid "should be different from the value of {}"
 msgstr "devrait être différent de la valeur de {}"
 
-#: tiramisu/option/baseoption.py:762
+#: tiramisu/option/baseoption.py:783
 msgid "must be different from the value of {}"
 msgstr "doit être différent de la valeur de {}"
 
-#: tiramisu/option/baseoption.py:766
+#: tiramisu/option/baseoption.py:787
 msgid "value for {} should be different"
 msgstr "valeur pour {} devrait être différent"
 
-#: tiramisu/option/baseoption.py:768
+#: tiramisu/option/baseoption.py:789
 msgid "value for {} must be different"
 msgstr "valeur pour {} doit être différent"
 
-#: tiramisu/option/baseoption.py:824
+#: tiramisu/option/baseoption.py:845
 msgid "default value not allowed if option: {0} is calculated"
 msgstr "la valeur par défaut n'est pas possible si l'option {0} est calculée"
 
-#: tiramisu/option/baseoption.py:844
+#: tiramisu/option/baseoption.py:865
 msgid "malformed requirements type for option: {0}, must be a dict"
 msgstr ""
 "type requirements malformé pour l'option : {0}, doit être un dictionnaire"
 
-#: tiramisu/option/baseoption.py:850
+#: tiramisu/option/baseoption.py:871
 msgid "malformed requirements for option: {0} unknown keys {1}, must only {2}"
 msgstr ""
 "requirements mal formés pour l'option : {0} clefs inconnues {1}, doit "
 "seulement avoir {2}"
 
-#: tiramisu/option/baseoption.py:858
+#: tiramisu/option/baseoption.py:879
 msgid ""
 "malformed requirements for option: {0} require must have option, expected "
 "and action keys"
@@ -332,33 +338,33 @@ msgstr ""
 "requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
 "option, expected et action"
 
-#: tiramisu/option/baseoption.py:865
+#: tiramisu/option/baseoption.py:886
 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/baseoption.py:870
+#: tiramisu/option/baseoption.py:891
 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/baseoption.py:874
+#: tiramisu/option/baseoption.py:895
 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/baseoption.py:878
+#: tiramisu/option/baseoption.py:899
 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/baseoption.py:882
+#: tiramisu/option/baseoption.py:903
 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/baseoption.py:885
+#: tiramisu/option/baseoption.py:906
 msgid ""
 "malformed requirements multi option must not set as requires of non multi "
 "option {0}"
@@ -366,18 +372,18 @@ msgstr ""
 "requirements mal formés une option multiple ne doit pas être spécifié comme "
 "pré-requis à l'option non multiple {0}"
 
-#: tiramisu/option/baseoption.py:891
+#: tiramisu/option/baseoption.py:912
 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/baseoption.py:896
+#: tiramisu/option/baseoption.py:917
 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/baseoption.py:924
+#: tiramisu/option/baseoption.py:945
 msgid "malformed symlinkoption must be an option for symlink {0}"
 msgstr "symlinkoption mal formé, doit être une option pour symlink {0}"
 
@@ -624,21 +630,24 @@ msgid "option description seems to be part of an other config"
 msgstr "l'option description semble faire parti d'une autre config"
 
 #: tiramisu/option/optiondescription.py:137
-msgid "malformed consistency option {0} must be a master/slaves"
+msgid "malformed consistency option \"{0}\" must be a master/slaves"
 msgstr ""
-"test de consistence mal formé pour l'option {0} doit être une maître/esclave"
+"test de consistence mal formé pour l'option \"{0}\" doit être une maître/"
+"esclave"
 
 #: tiramisu/option/optiondescription.py:144
-msgid "malformed consistency option {0} must not be a multi for {1}"
+msgid "malformed consistency option \"{0}\" must not be a multi for \"{1}\""
 msgstr ""
-"test de consistence mal formé pour l'option {0} ne doit doit pas être une "
-"liste pour {1}"
+"test de consistence mal formé pour l'option \"{0}\" ne doit doit pas être "
+"une liste pour \"{1}\""
 
 #: tiramisu/option/optiondescription.py:148
-msgid "malformed consistency option {0} must be in same master/slaves for {1}"
+msgid ""
+"malformed consistency option \"{0}\" must be in same master/slaves for "
+"\"{1}\""
 msgstr ""
-"test de consistence mal formé pour l'option {0} doit être dans la même "
-"maître/esclave pour {1}"
+"test de consistence mal formé pour l'option \"{0}\" doit être dans la même "
+"maître/esclave pour \"{1}\""
 
 #: tiramisu/option/optiondescription.py:173
 msgid "malformed requirements option {0} must be in same master/slaves for {1}"
@@ -897,6 +906,22 @@ msgstr "ne peut étendre une option multi {0} pour une maître ou une esclave"
 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"
 
+#~ msgid "malformed consistency option {0} must be a master/slaves"
+#~ msgstr ""
+#~ "test de consistence mal formé pour l'option {0} doit être une maître/"
+#~ "esclave"
+
+#~ msgid "malformed consistency option {0} must not be a multi for {1}"
+#~ msgstr ""
+#~ "test de consistence mal formé pour l'option {0} ne doit doit pas être une "
+#~ "liste pour {1}"
+
+#~ msgid ""
+#~ "malformed consistency option {0} must be in same master/slaves for {1}"
+#~ msgstr ""
+#~ "test de consistence mal formé pour l'option {0} doit être dans la même "
+#~ "maître/esclave pour {1}"
+
 #~ msgid "invalid value for option {0}: {1}"
 #~ msgstr "valeur invalide pour l'option {0} : {1}"
 
index 3187966..cbfa9af 100644 (file)
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2016-11-14 21:31+CET\n"
+"POT-Creation-Date: 2016-11-16 22:25+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"
@@ -116,219 +116,223 @@ msgstr ""
 msgid " {} "
 msgstr ""
 
-#: tiramisu/error.py:49
+#: tiramisu/error.py:52
 msgid "property"
 msgstr ""
 
-#: tiramisu/error.py:51
+#: tiramisu/error.py:54
 msgid "properties"
 msgstr ""
 
-#: tiramisu/error.py:53 tiramisu/setting.py:517
+#: tiramisu/error.py:56 tiramisu/setting.py:517
 msgid "cannot access to {0} \"{1}\" because has {2} {3}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:58
+#: tiramisu/option/baseoption.py:63
 msgid "{0} must be a function"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:61
+#: tiramisu/option/baseoption.py:66
 msgid "{0}_params must be a dict"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:64
+#: tiramisu/option/baseoption.py:69
 msgid "{0}_params with key {1} mustn't have length different to 1"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:68
+#: tiramisu/option/baseoption.py:73
 msgid "{0}_params must be tuple for key \"{1}\""
 msgstr ""
 
-#: tiramisu/option/baseoption.py:74
+#: tiramisu/option/baseoption.py:79
 msgid "{0}_params with length of tuple as 1 must only have None as first value"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:78
+#: tiramisu/option/baseoption.py:83
 msgid "{0}_params must only have 1 or 2 as length"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:84
+#: tiramisu/option/baseoption.py:89
 msgid "{0}_params must have an option not a {0} for first argument"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:88
+#: tiramisu/option/baseoption.py:93
 msgid "{0}_params must have a boolean not a {0} for second argument"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:105
+#: tiramisu/option/baseoption.py:110
 msgid "invalid name: {0} for option"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:107
+#: tiramisu/option/baseoption.py:112
 msgid "default_multi is set whereas multi is False in option: {0}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:119
+#: tiramisu/option/baseoption.py:124
 msgid "invalid multi value"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:129
+#: tiramisu/option/baseoption.py:134
 msgid "invalid properties type {0} for {1}, must be a tuple"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:168
+#: tiramisu/option/baseoption.py:173
 msgid "params defined for a callback function but no callback defined yet for option {0}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:173
+#: tiramisu/option/baseoption.py:178
 msgid "a callback is already set for option {0}, cannot set another one's"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:257
+#: tiramisu/option/baseoption.py:262
 msgid "cannot serialize Option, only in OptionDescription"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:338 tiramisu/storage/dictionary/option.py:119
+#: tiramisu/option/baseoption.py:343 tiramisu/storage/dictionary/option.py:119
 msgid "'{0}' ({1}) object attribute '{2}' is read-only"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:359
+#: tiramisu/option/baseoption.py:364
 msgid "invalid string"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:362
+#: tiramisu/option/baseoption.py:367
 msgid "invalid unicode or string"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:515 tiramisu/option/baseoption.py:560
+#: tiramisu/option/baseoption.py:532 tiramisu/option/baseoption.py:577
 msgid "\"{0}\" is an invalid {1} for \"{2}\", {3}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:519 tiramisu/option/baseoption.py:564
+#: tiramisu/option/baseoption.py:536 tiramisu/option/baseoption.py:581
 msgid "\"{0}\" is an invalid {1} for \"{2}\""
 msgstr ""
 
-#: tiramisu/option/baseoption.py:531
+#: tiramisu/option/baseoption.py:548
 msgid "do_validation for {0}: error in value"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:550
+#: tiramisu/option/baseoption.py:567
 msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\", {3}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:580 tiramisu/option/baseoption.py:590
+#: tiramisu/option/baseoption.py:597 tiramisu/option/baseoption.py:607
 msgid "invalid value {0} for option {1} which must be a list"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:596
+#: tiramisu/option/baseoption.py:613
 msgid "invalid value {0} for option {1} which must be a list of list"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:647 tiramisu/option/baseoption.py:651
+#: tiramisu/option/baseoption.py:664 tiramisu/option/baseoption.py:668
 msgid "cannot add consistency with submulti option"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:653
+#: tiramisu/option/baseoption.py:670
 msgid "consistency must be set with an option"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:656 tiramisu/option/baseoption.py:663
+#: tiramisu/option/baseoption.py:673 tiramisu/option/baseoption.py:680
 msgid "almost one option in consistency is in a dynoptiondescription but not all"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:659
+#: tiramisu/option/baseoption.py:676
 msgid "option in consistency must be in same dynoptiondescription"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:666
+#: tiramisu/option/baseoption.py:683
 msgid "cannot add consistency with itself"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:668
+#: tiramisu/option/baseoption.py:685
 msgid "every options in consistency must be multi or none"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:685
+#: tiramisu/option/baseoption.py:702
 msgid "'{0}' ({1}) cannot add consistency, option is read-only"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:692
+#: tiramisu/option/baseoption.py:709
 msgid "consistency {0} not available for this option"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:696
+#: tiramisu/option/baseoption.py:713
 msgid "unknow parameter {0} in consistency"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:757
+#: tiramisu/option/baseoption.py:773
 msgid "_cons_not_equal: {} are not different"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:760
+#: tiramisu/option/baseoption.py:777
+msgid "this value is already present"
+msgstr ""
+
+#: tiramisu/option/baseoption.py:781
 msgid "should be different from the value of {}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:762
+#: tiramisu/option/baseoption.py:783
 msgid "must be different from the value of {}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:766
+#: tiramisu/option/baseoption.py:787
 msgid "value for {} should be different"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:768
+#: tiramisu/option/baseoption.py:789
 msgid "value for {} must be different"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:824
+#: tiramisu/option/baseoption.py:845
 msgid "default value not allowed if option: {0} is calculated"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:844
+#: tiramisu/option/baseoption.py:865
 msgid "malformed requirements type for option: {0}, must be a dict"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:850
+#: tiramisu/option/baseoption.py:871
 msgid "malformed requirements for option: {0} unknown keys {1}, must only {2}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:858
+#: tiramisu/option/baseoption.py:879
 msgid "malformed requirements for option: {0} require must have option, expected and action keys"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:865
+#: tiramisu/option/baseoption.py:886
 msgid "malformed requirements for option: {0} action cannot be force_store_value"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:870
+#: tiramisu/option/baseoption.py:891
 msgid "malformed requirements for option: {0} inverse must be boolean"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:874
+#: tiramisu/option/baseoption.py:895
 msgid "malformed requirements for option: {0} transitive must be boolean"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:878
+#: tiramisu/option/baseoption.py:899
 msgid "malformed requirements for option: {0} same_action must be boolean"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:882
+#: tiramisu/option/baseoption.py:903
 msgid "malformed requirements must be an option in option {0}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:885
+#: tiramisu/option/baseoption.py:906
 msgid "malformed requirements multi option must not set as requires of non multi option {0}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:891
+#: tiramisu/option/baseoption.py:912
 msgid "malformed requirements second argument must be valid for option {0}: {1}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:896
+#: tiramisu/option/baseoption.py:917
 msgid "inconsistency in action types for option: {0} action: {1}"
 msgstr ""
 
-#: tiramisu/option/baseoption.py:924
+#: tiramisu/option/baseoption.py:945
 msgid "malformed symlinkoption must be an option for symlink {0}"
 msgstr ""
 
@@ -573,15 +577,15 @@ msgid "option description seems to be part of an other config"
 msgstr ""
 
 #: tiramisu/option/optiondescription.py:137
-msgid "malformed consistency option {0} must be a master/slaves"
+msgid "malformed consistency option \"{0}\" must be a master/slaves"
 msgstr ""
 
 #: tiramisu/option/optiondescription.py:144
-msgid "malformed consistency option {0} must not be a multi for {1}"
+msgid "malformed consistency option \"{0}\" must not be a multi for \"{1}\""
 msgstr ""
 
 #: tiramisu/option/optiondescription.py:148
-msgid "malformed consistency option {0} must be in same master/slaves for {1}"
+msgid "malformed consistency option \"{0}\" must be in same master/slaves for \"{1}\""
 msgstr ""
 
 #: tiramisu/option/optiondescription.py:173