for a multi mandatory, allow [] with allow_empty_list attribut

This commit is contained in:
Emmanuel Garette 2015-04-20 14:49:43 +02:00
parent 072246a203
commit 487b99b32c
6 changed files with 73 additions and 14 deletions

View file

@ -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> Sun Apr 19 09:14:21 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* valid Option is an unicode or a string if needed * valid Option is an unicode or a string if needed
* difference between option/optiondescription in PropertiesOptionError * difference between option/optiondescription in PropertiesOptionError

View file

@ -16,7 +16,9 @@ def make_description():
properties=('mandatory', )) properties=('mandatory', ))
stroption3 = StrOption('str3', 'Test string option', multi=True, stroption3 = StrOption('str3', 'Test string option', multi=True,
properties=('mandatory', )) 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 return descr
@ -123,6 +125,17 @@ def test_mandatory_multi_none():
def test_mandatory_multi_empty(): def test_mandatory_multi_empty():
descr = make_description() descr = make_description()
config = Config(descr) 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 = [''] config.str3 = ['']
assert config.getowner(config.unwrap_from_path('str3')) == 'user' assert config.getowner(config.unwrap_from_path('str3')) == 'user'
config.read_only() config.read_only()
@ -132,6 +145,7 @@ def test_mandatory_multi_empty():
except PropertiesOptionError as err: except PropertiesOptionError as err:
prop = err.proptype prop = err.proptype
assert 'mandatory' in prop assert 'mandatory' in prop
#
config.read_write() config.read_write()
config.str3 = ['yes', ''] config.str3 = ['yes', '']
assert config.getowner(config.unwrap_from_path('str3')) == 'user' assert config.getowner(config.unwrap_from_path('str3')) == 'user'
@ -144,6 +158,38 @@ def test_mandatory_multi_empty():
assert 'mandatory' in prop 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(): def test_mandatory_multi_append():
descr = make_description() descr = make_description()
config = Config(descr) config = Config(descr)

View file

@ -99,7 +99,7 @@ class Base(StorageBase):
def __init__(self, name, doc, default=None, default_multi=None, def __init__(self, name, doc, default=None, default_multi=None,
requires=None, multi=False, callback=None, requires=None, multi=False, callback=None,
callback_params=None, validator=None, validator_params=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 if not valid_name(name): # pragma: optional cover
raise ValueError(_("invalid name: {0} for option").format(name)) raise ValueError(_("invalid name: {0} for option").format(name))
if requires is not None: if requires is not None:
@ -134,7 +134,7 @@ class Base(StorageBase):
'requirement {0}'.format( 'requirement {0}'.format(
list(set_forbidden_properties))) list(set_forbidden_properties)))
StorageBase.__init__(self, name, _multi, warnings_only, doc, extra, 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: if multi is not False and default is None:
default = [] default = []
self.impl_validate(default) self.impl_validate(default)
@ -905,7 +905,7 @@ class SymLinkOption(OnlyOption):
'for symlink {0}').format(name)) 'for symlink {0}').format(name))
super(Base, self).__init__(name, undefined, undefined, undefined, super(Base, self).__init__(name, undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
opt) False, opt)
self.commit() self.commit()
def __getattr__(self, name, context=undefined): def __getattr__(self, name, context=undefined):

View file

@ -467,7 +467,7 @@ class Settings(object):
else: else:
if 'mandatory' in properties and \ if 'mandatory' in properties and \
not self._getcontext().cfgimpl_get_values()._isempty( 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') properties.remove('mandatory')
if is_write and 'everything_frozen' in self_properties: if is_write and 'everything_frozen' in self_properties:
properties.add('frozen') properties.add('frozen')

View file

@ -32,7 +32,8 @@ class StorageBase(object):
'_multi', '_multi',
'_extra', '_extra',
'_warnings_only', '_warnings_only',
#valeur '_allow_empty_list',
#value
'_default', '_default',
'_default_multi', '_default_multi',
#calcul #calcul
@ -41,10 +42,7 @@ class StorageBase(object):
'_properties', '_properties',
'_calc_properties', '_calc_properties',
'_val_call', '_val_call',
#'_validator', #
#'_validator_params',
#'_callback',
#'_callback_params',
'_consistencies', '_consistencies',
'_master_slaves', '_master_slaves',
'_choice_values', '_choice_values',
@ -62,7 +60,7 @@ class StorageBase(object):
) )
def __init__(self, name, multi, warnings_only, doc, extra, calc_properties, 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 self._name = name
if doc is not undefined: if doc is not undefined:
self._informations = {'doc': doc} self._informations = {'doc': doc}
@ -81,6 +79,8 @@ class StorageBase(object):
self._properties = properties self._properties = properties
if opt is not undefined: if opt is not undefined:
self._opt = opt 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): def _set_default_values(self, default, default_multi):
if ((self.impl_is_multi() and default != tuple()) or if ((self.impl_is_multi() and default != tuple()) or
@ -298,6 +298,13 @@ class StorageBase(object):
_multi = 1 _multi = 1
return _multi == 2 return _multi == 2
def impl_allow_empty_list(self):
try:
return self._allow_empty_list
except AttributeError:
return False
def _get_extra(self, key): def _get_extra(self, key):
extra = self._extra extra = self._extra
if isinstance(extra, tuple): if isinstance(extra, tuple):
@ -308,7 +315,7 @@ class StorageBase(object):
def _is_warnings_only(self): def _is_warnings_only(self):
try: try:
return self._warnings_only return self._warnings_only
except: except AttributeError:
return False return False
def impl_getdefault(self): def impl_getdefault(self):

View file

@ -175,13 +175,13 @@ class Values(object):
if hasvalue: if hasvalue:
self._p_.resetvalue(path) 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" "convenience method to know if an option is empty"
empty = opt._empty empty = opt._empty
if value is not undefined: if value is not undefined:
empty_not_multi = not opt.impl_is_multi() and (value is None or empty_not_multi = not opt.impl_is_multi() and (value is None or
value == empty) 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 None in value or
empty in value) empty in value)
else: else: