for a multi mandatory, allow [] with allow_empty_list attribut
authorEmmanuel Garette <egarette@cadoles.com>
Mon, 20 Apr 2015 12:49:43 +0000 (14:49 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Mon, 20 Apr 2015 12:49:43 +0000 (14:49 +0200)
ChangeLog
test/test_mandatory.py
tiramisu/option/baseoption.py
tiramisu/setting.py
tiramisu/storage/dictionary/option.py
tiramisu/value.py

index f52827a..9f17778 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Apr 20 14:44:15 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
+       * if option is multi, the properties disallow [None] for a multi but
+       [] too, with allow_empty_list to True, [None] is not allowed, but you
+       can have empty list (so [])
+
+
 Sun Apr 19 09:14:21 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
        * valid Option is an unicode or a string if needed
        * difference between option/optiondescription in PropertiesOptionError
index ae73418..374e2aa 100644 (file)
@@ -16,7 +16,9 @@ def make_description():
                                properties=('mandatory', ))
     stroption3 = StrOption('str3', 'Test string option', multi=True,
                            properties=('mandatory', ))
-    descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
+    stroption4 = StrOption('str4', 'Test string option', multi=True,
+                           properties=('mandatory', ), allow_empty_list=True)
+    descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, stroption4])
     return descr
 
 
@@ -123,6 +125,17 @@ def test_mandatory_multi_none():
 def test_mandatory_multi_empty():
     descr = make_description()
     config = Config(descr)
+    config.str3 = []
+    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
+    config.read_only()
+    prop = []
+    try:
+        config.str3
+    except PropertiesOptionError as err:
+        prop = err.proptype
+    assert 'mandatory' in prop
+    #
+    config.read_write()
     config.str3 = ['']
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
     config.read_only()
@@ -132,6 +145,7 @@ def test_mandatory_multi_empty():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    #
     config.read_write()
     config.str3 = ['yes', '']
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
@@ -144,6 +158,38 @@ def test_mandatory_multi_empty():
     assert 'mandatory' in prop
 
 
+def test_mandatory_multi_empty_allow_empty_list():
+    descr = make_description()
+    config = Config(descr)
+    config.str4 = []
+    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
+    config.read_only()
+    prop = []
+    config.str4
+    #
+    config.read_write()
+    config.str4 = ['']
+    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
+    config.read_only()
+    prop = []
+    try:
+        config.str4
+    except PropertiesOptionError as err:
+        prop = err.proptype
+    assert 'mandatory' in prop
+    #
+    config.read_write()
+    config.str4 = ['yes', '']
+    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
+    config.read_only()
+    prop = []
+    try:
+        config.str4
+    except PropertiesOptionError as err:
+        prop = err.proptype
+    assert 'mandatory' in prop
+
+
 def test_mandatory_multi_append():
     descr = make_description()
     config = Config(descr)
index ef57b71..5cece57 100644 (file)
@@ -99,7 +99,7 @@ class Base(StorageBase):
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
                  callback_params=None, validator=None, validator_params=None,
-                 properties=None, warnings_only=False, extra=None):
+                 properties=None, warnings_only=False, extra=None, allow_empty_list=False):
         if not valid_name(name):  # pragma: optional cover
             raise ValueError(_("invalid name: {0} for option").format(name))
         if requires is not None:
@@ -134,7 +134,7 @@ class Base(StorageBase):
                                  'requirement {0}'.format(
                                      list(set_forbidden_properties)))
         StorageBase.__init__(self, name, _multi, warnings_only, doc, extra,
-                             calc_properties, requires, properties)
+                             calc_properties, requires, properties, allow_empty_list)
         if multi is not False and default is None:
             default = []
         self.impl_validate(default)
@@ -905,7 +905,7 @@ class SymLinkOption(OnlyOption):
                                'for symlink {0}').format(name))
         super(Base, self).__init__(name, undefined, undefined, undefined,
                                    undefined, undefined, undefined, undefined,
-                                   opt)
+                                   False, opt)
         self.commit()
 
     def __getattr__(self, name, context=undefined):
index dfe48a4..c3dd947 100644 (file)
@@ -467,7 +467,7 @@ class Settings(object):
         else:
             if 'mandatory' in properties and \
                     not self._getcontext().cfgimpl_get_values()._isempty(
-                        opt_or_descr, value):
+                        opt_or_descr, value, opt_or_descr.impl_allow_empty_list()):
                 properties.remove('mandatory')
             if is_write and 'everything_frozen' in self_properties:
                 properties.add('frozen')
index f6b19b3..219e606 100644 (file)
@@ -32,7 +32,8 @@ class StorageBase(object):
                  '_multi',
                  '_extra',
                  '_warnings_only',
-                 #valeur
+                 '_allow_empty_list',
+                 #value
                  '_default',
                  '_default_multi',
                  #calcul
@@ -41,10 +42,7 @@ class StorageBase(object):
                  '_properties',
                  '_calc_properties',
                  '_val_call',
-                 #'_validator',
-                 #'_validator_params',
-                 #'_callback',
-                 #'_callback_params',
+                 #
                  '_consistencies',
                  '_master_slaves',
                  '_choice_values',
@@ -62,7 +60,7 @@ class StorageBase(object):
                  )
 
     def __init__(self, name, multi, warnings_only, doc, extra, calc_properties,
-                 requires, properties, opt=undefined):
+                 requires, properties, allow_empty_list, opt=undefined):
         self._name = name
         if doc is not undefined:
             self._informations = {'doc': doc}
@@ -81,6 +79,8 @@ class StorageBase(object):
             self._properties = properties
         if opt is not undefined:
             self._opt = opt
+        if allow_empty_list is not False:
+            self._allow_empty_list = allow_empty_list
 
     def _set_default_values(self, default, default_multi):
         if ((self.impl_is_multi() and default != tuple()) or
@@ -298,6 +298,13 @@ class StorageBase(object):
             _multi = 1
         return _multi == 2
 
+    def impl_allow_empty_list(self):
+        try:
+            return self._allow_empty_list
+        except AttributeError:
+            return False
+
+
     def _get_extra(self, key):
         extra = self._extra
         if isinstance(extra, tuple):
@@ -308,7 +315,7 @@ class StorageBase(object):
     def _is_warnings_only(self):
         try:
             return self._warnings_only
-        except:
+        except AttributeError:
             return False
 
     def impl_getdefault(self):
index 6c14315..2305d6f 100644 (file)
@@ -175,13 +175,13 @@ class Values(object):
         if hasvalue:
             self._p_.resetvalue(path)
 
-    def _isempty(self, opt, value):
+    def _isempty(self, opt, value, allow_empty_list):
         "convenience method to know if an option is empty"
         empty = opt._empty
         if value is not undefined:
             empty_not_multi = not opt.impl_is_multi() and (value is None or
                                                            value == empty)
-            empty_multi = opt.impl_is_multi() and (value == [] or
+            empty_multi = opt.impl_is_multi() and ((not allow_empty_list and value == []) or
                                                    None in value or
                                                    empty in value)
         else: