when change len of calculated master, change len of slave too
This commit is contained in:
parent
71b235551e
commit
683e40fbb5
|
@ -373,6 +373,9 @@ def test_callback_multi_value():
|
||||||
assert cfg.val2 == ['val']
|
assert cfg.val2 == ['val']
|
||||||
assert cfg.val3 == ['yes']
|
assert cfg.val3 == ['yes']
|
||||||
assert cfg.val4 == ['val', 'yes']
|
assert cfg.val4 == ['val', 'yes']
|
||||||
|
cfg.val2.append('new')
|
||||||
|
assert cfg.val1 == ['val']
|
||||||
|
assert cfg.val2 == ['val', 'new']
|
||||||
|
|
||||||
|
|
||||||
def test_callback_multi_list():
|
def test_callback_multi_list():
|
||||||
|
@ -466,6 +469,66 @@ def test_callback_master_and_slaves_slave():
|
||||||
assert cfg.val1.val2 == ['val2', 'val2', 'val']
|
assert cfg.val1.val2 == ['val2', 'val2', 'val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_slave_cal():
|
||||||
|
val3 = StrOption('val3', "", multi=True)
|
||||||
|
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
|
||||||
|
val2 = StrOption('val2', "", multi=True, callback=return_val)
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val3 == []
|
||||||
|
assert cfg.val1.val1 == []
|
||||||
|
assert cfg.val1.val2 == []
|
||||||
|
cfg.val1.val1 = ['val1']
|
||||||
|
cfg.val3 = ['val1']
|
||||||
|
assert cfg.val1.val1 == ['val1']
|
||||||
|
assert cfg.val1.val2 == ['val']
|
||||||
|
assert cfg.val1.val1 == ['val1']
|
||||||
|
assert cfg.val1.val2 == ['val']
|
||||||
|
del(cfg.val1.val1)
|
||||||
|
cfg.val1.val2 = ['val']
|
||||||
|
cfg.val3 = ['val1', 'val2']
|
||||||
|
assert cfg.val1.val2 == ['val', 'val']
|
||||||
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
|
cfg.val1.val2 = ['val1', 'val2']
|
||||||
|
cfg.val3.pop(1)
|
||||||
|
# cannot remove slave's value because master is calculated
|
||||||
|
# so raise
|
||||||
|
raises(SlaveError, "cfg.val1.val1")
|
||||||
|
raises(SlaveError, "cfg.val1.val2")
|
||||||
|
cfg.val3 = ['val1', 'val2', 'val3']
|
||||||
|
assert cfg.val1.val2 == ['val1', 'val2', 'val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_slave_cal2():
|
||||||
|
val3 = StrOption('val3', "", ['val', 'val'], multi=True)
|
||||||
|
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
|
||||||
|
val2 = StrOption('val2', "", ['val2', 'val2'], multi=True)
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val3 == ['val', 'val']
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == ['val2', 'val2']
|
||||||
|
cfg.val3.pop(1)
|
||||||
|
# # cannot remove slave's value because master is calculated
|
||||||
|
# # so raise
|
||||||
|
raises(SlaveError, "cfg.val1.val1")
|
||||||
|
raises(SlaveError, "cfg.val1.val2")
|
||||||
|
cfg.val3 = ['val', 'val']
|
||||||
|
assert cfg.val3 == ['val', 'val']
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == ['val2', 'val2']
|
||||||
|
raises(SlaveError, "cfg.val1.val1 = ['val']")
|
||||||
|
assert cfg.val3 == ['val', 'val']
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == ['val2', 'val2']
|
||||||
|
|
||||||
|
|
||||||
def test_callback_master_and_slaves_slave_list():
|
def test_callback_master_and_slaves_slave_list():
|
||||||
val1 = StrOption('val1', "", multi=True)
|
val1 = StrOption('val1', "", multi=True)
|
||||||
val2 = StrOption('val2', "", multi=True, callback=return_list)
|
val2 = StrOption('val2', "", multi=True, callback=return_list)
|
||||||
|
|
|
@ -249,3 +249,46 @@ def test_state_values_owner():
|
||||||
delete_session('29090931')
|
delete_session('29090931')
|
||||||
except ConfigError:
|
except ConfigError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_unkown_setting_owner():
|
||||||
|
"""load an unknow _owner, should create it"""
|
||||||
|
assert not 'supernewuser' in owners.__dict__
|
||||||
|
loads("""ccopy_reg
|
||||||
|
_reconstructor
|
||||||
|
p0
|
||||||
|
(ctiramisu.setting
|
||||||
|
Settings
|
||||||
|
p1
|
||||||
|
c__builtin__
|
||||||
|
object
|
||||||
|
p2
|
||||||
|
Ntp3
|
||||||
|
Rp4
|
||||||
|
(dp5
|
||||||
|
S'_owner'
|
||||||
|
p6
|
||||||
|
S'supernewuser'
|
||||||
|
p7
|
||||||
|
sS'_p_'
|
||||||
|
p8
|
||||||
|
g0
|
||||||
|
(ctiramisu.storage.dictionary.setting
|
||||||
|
Settings
|
||||||
|
p9
|
||||||
|
g2
|
||||||
|
Ntp10
|
||||||
|
Rp11
|
||||||
|
(dp12
|
||||||
|
S'_cache'
|
||||||
|
p13
|
||||||
|
(dp14
|
||||||
|
sS'_permissives'
|
||||||
|
p15
|
||||||
|
(dp16
|
||||||
|
sS'_properties'
|
||||||
|
p17
|
||||||
|
(dp18
|
||||||
|
sbsb.
|
||||||
|
.""")
|
||||||
|
assert 'supernewuser' in owners.__dict__
|
||||||
|
|
|
@ -152,7 +152,10 @@ def carry_out_calculation(option, config, callback, callback_params,
|
||||||
opt)
|
opt)
|
||||||
# get value
|
# get value
|
||||||
try:
|
try:
|
||||||
value = config._getattr(path, force_permissive=True)
|
value = config._getattr(path, force_permissive=True, validate=False)
|
||||||
|
# convert to list, not modifie this multi
|
||||||
|
if value.__class__.__name__ == 'Multi':
|
||||||
|
value = list(value)
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
if force_permissive:
|
if force_permissive:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -73,7 +73,7 @@ class Values(object):
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _getvalue(self, opt, path, validate=True):
|
def _getvalue(self, opt, path):
|
||||||
"""actually retrieves the value
|
"""actually retrieves the value
|
||||||
|
|
||||||
:param opt: the `option.Option()` object
|
:param opt: the `option.Option()` object
|
||||||
|
@ -82,14 +82,9 @@ class Values(object):
|
||||||
if not self._p_.hasvalue(path):
|
if not self._p_.hasvalue(path):
|
||||||
# if there is no value
|
# if there is no value
|
||||||
value = self._getdefault(opt)
|
value = self._getdefault(opt)
|
||||||
if opt.impl_is_multi():
|
|
||||||
value = Multi(value, self.context, opt, path, validate)
|
|
||||||
else:
|
else:
|
||||||
# if there is a value
|
# if there is a value
|
||||||
value = self._p_.getvalue(path)
|
value = self._p_.getvalue(path)
|
||||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
|
||||||
# load value so don't need to validate if is not a Multi
|
|
||||||
value = Multi(value, self.context, opt, path, validate=False)
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def get_modified_values(self):
|
def get_modified_values(self):
|
||||||
|
@ -198,7 +193,7 @@ class Values(object):
|
||||||
# ConfigError if properties did not raise.
|
# ConfigError if properties did not raise.
|
||||||
config_error = None
|
config_error = None
|
||||||
force_permissives = None
|
force_permissives = None
|
||||||
# if value is callback and is not set
|
# if value has callback and is not set
|
||||||
# or frozen with force_default_on_freeze
|
# or frozen with force_default_on_freeze
|
||||||
if opt.impl_has_callback() and (
|
if opt.impl_has_callback() and (
|
||||||
self._is_default_owner(path) or
|
self._is_default_owner(path) or
|
||||||
|
@ -208,7 +203,7 @@ class Values(object):
|
||||||
if (opt.impl_is_multi() and
|
if (opt.impl_is_multi() and
|
||||||
opt.impl_get_multitype() == multitypes.slave):
|
opt.impl_get_multitype() == multitypes.slave):
|
||||||
masterp = self._get_opt_path(opt.impl_get_master_slaves())
|
masterp = self._get_opt_path(opt.impl_get_master_slaves())
|
||||||
mastervalue = getattr(context, masterp)
|
mastervalue = context._getattr(masterp, validate=validate)
|
||||||
lenmaster = len(mastervalue)
|
lenmaster = len(mastervalue)
|
||||||
if lenmaster == 0:
|
if lenmaster == 0:
|
||||||
value = []
|
value = []
|
||||||
|
@ -240,7 +235,10 @@ class Values(object):
|
||||||
if opt.impl_is_multi():
|
if opt.impl_is_multi():
|
||||||
value = Multi(value, self.context, opt, path, validate)
|
value = Multi(value, self.context, opt, path, validate)
|
||||||
else:
|
else:
|
||||||
value = self._getvalue(opt, path, validate)
|
value = self._getvalue(opt, path)
|
||||||
|
if opt.impl_is_multi():
|
||||||
|
# load value so don't need to validate if is not a Multi
|
||||||
|
value = Multi(value, self.context, opt, path, validate=validate)
|
||||||
if config_error is None and validate:
|
if config_error is None and validate:
|
||||||
opt.impl_validate(value, context, 'validator' in setting)
|
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(path) and \
|
||||||
|
@ -266,10 +264,27 @@ class Values(object):
|
||||||
context = self._getcontext()
|
context = self._getcontext()
|
||||||
opt.impl_validate(value, context,
|
opt.impl_validate(value, context,
|
||||||
'validator' in context.cfgimpl_get_settings())
|
'validator' in context.cfgimpl_get_settings())
|
||||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
if opt.impl_is_multi():
|
||||||
value = Multi(value, self.context, opt, path, setitem=True)
|
value = Multi(value, self.context, opt, path, setitem=True)
|
||||||
|
# Save old value
|
||||||
|
if opt.impl_get_multitype() == multitypes.master and \
|
||||||
|
self._p_.hasvalue(path):
|
||||||
|
old_value = self._p_.getvalue(path)
|
||||||
|
old_owner = self._p_.getowner(path, None)
|
||||||
|
else:
|
||||||
|
old_value = undefined
|
||||||
|
old_owner = undefined
|
||||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||||
is_write=is_write)
|
is_write=is_write)
|
||||||
|
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master:
|
||||||
|
try:
|
||||||
|
value._valid_master()
|
||||||
|
except Exception, err:
|
||||||
|
if old_value is not undefined:
|
||||||
|
self._p_.setvalue(path, old_value, old_owner)
|
||||||
|
else:
|
||||||
|
self._p_.resetvalue(path)
|
||||||
|
raise err
|
||||||
|
|
||||||
def _setvalue(self, opt, path, value, force_permissive=False,
|
def _setvalue(self, opt, path, value, force_permissive=False,
|
||||||
force_properties=None,
|
force_properties=None,
|
||||||
|
@ -283,6 +298,8 @@ class Values(object):
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
force_properties=force_properties)
|
force_properties=force_properties)
|
||||||
owner = context.cfgimpl_get_settings().getowner()
|
owner = context.cfgimpl_get_settings().getowner()
|
||||||
|
if isinstance(value, Multi):
|
||||||
|
value = list(value)
|
||||||
self._p_.setvalue(path, value, owner)
|
self._p_.setvalue(path, value, owner)
|
||||||
|
|
||||||
def getowner(self, opt):
|
def getowner(self, opt):
|
||||||
|
@ -403,6 +420,8 @@ class Multi(list):
|
||||||
:param opt: the option object that have this Multi value
|
:param opt: the option object that have this Multi value
|
||||||
:param setitem: only if set a value
|
:param setitem: only if set a value
|
||||||
"""
|
"""
|
||||||
|
if isinstance(value, Multi):
|
||||||
|
raise ValueError(_('{0} is already a Multi ').format(opt._name))
|
||||||
self.opt = opt
|
self.opt = opt
|
||||||
self.path = path
|
self.path = path
|
||||||
if not isinstance(context, weakref.ReferenceType):
|
if not isinstance(context, weakref.ReferenceType):
|
||||||
|
@ -412,8 +431,9 @@ class Multi(list):
|
||||||
value = [value]
|
value = [value]
|
||||||
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
||||||
value = self._valid_slave(value, setitem)
|
value = self._valid_slave(value, setitem)
|
||||||
elif validate and self.opt.impl_get_multitype() == multitypes.master:
|
elif not setitem and validate and \
|
||||||
self._valid_master(value)
|
self.opt.impl_get_multitype() == multitypes.master:
|
||||||
|
self._valid_master()
|
||||||
super(Multi, self).__init__(value)
|
super(Multi, self).__init__(value)
|
||||||
|
|
||||||
def _getcontext(self):
|
def _getcontext(self):
|
||||||
|
@ -433,12 +453,10 @@ class Multi(list):
|
||||||
values = context.cfgimpl_get_values()
|
values = context.cfgimpl_get_values()
|
||||||
masterp = context.cfgimpl_get_description().impl_get_path_by_opt(
|
masterp = context.cfgimpl_get_description().impl_get_path_by_opt(
|
||||||
self.opt.impl_get_master_slaves())
|
self.opt.impl_get_master_slaves())
|
||||||
mastervalue = getattr(context, masterp)
|
mastervalue = context._getattr(masterp, validate=False)
|
||||||
masterlen = len(mastervalue)
|
masterlen = len(mastervalue)
|
||||||
valuelen = len(value)
|
valuelen = len(value)
|
||||||
is_default_owner = not values._is_default_owner(self.path) or setitem
|
if valuelen > masterlen or (valuelen < masterlen and setitem):
|
||||||
if valuelen > masterlen or (valuelen < masterlen and
|
|
||||||
is_default_owner):
|
|
||||||
raise SlaveError(_("invalid len for the slave: {0}"
|
raise SlaveError(_("invalid len for the slave: {0}"
|
||||||
" which has {1} as master").format(
|
" which has {1} as master").format(
|
||||||
self.opt._name, masterp))
|
self.opt._name, masterp))
|
||||||
|
@ -455,30 +473,12 @@ class Multi(list):
|
||||||
#else: same len so do nothing
|
#else: same len so do nothing
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _valid_master(self, value):
|
def _valid_master(self):
|
||||||
masterlen = len(value)
|
#masterlen = len(value)
|
||||||
values = self._getcontext().cfgimpl_get_values()
|
values = self._getcontext().cfgimpl_get_values()
|
||||||
for slave in self.opt._master_slaves:
|
for slave in self.opt._master_slaves:
|
||||||
path = values._get_opt_path(slave)
|
path = values._get_opt_path(slave)
|
||||||
if not values._is_default_owner(path):
|
Multi(values._getvalue(slave, path), self.context, slave, path)
|
||||||
value_slave = values._getvalue(slave, path)
|
|
||||||
if len(value_slave) > masterlen:
|
|
||||||
raise SlaveError(_("invalid len for the master: {0}"
|
|
||||||
" which has {1} as slave with"
|
|
||||||
" greater len").format(
|
|
||||||
self.opt._name, slave._name))
|
|
||||||
elif len(value_slave) < masterlen:
|
|
||||||
for num in range(0, masterlen - len(value_slave)):
|
|
||||||
if slave.impl_has_callback():
|
|
||||||
# if callback add a value, but this value will not
|
|
||||||
# change anymore automaticly (because this value
|
|
||||||
# has owner)
|
|
||||||
index = value_slave.__len__()
|
|
||||||
value_slave.append(
|
|
||||||
values._getcallback_value(slave, index=index),
|
|
||||||
force=True)
|
|
||||||
else:
|
|
||||||
value_slave.append(undefined, force=True)
|
|
||||||
|
|
||||||
def __setitem__(self, index, value):
|
def __setitem__(self, index, value):
|
||||||
self._validate(value, index)
|
self._validate(value, index)
|
||||||
|
@ -518,16 +518,15 @@ class Multi(list):
|
||||||
dvalue = values._getcallback_value(slave, index=index)
|
dvalue = values._getcallback_value(slave, index=index)
|
||||||
else:
|
else:
|
||||||
dvalue = slave.impl_getdefault_multi()
|
dvalue = slave.impl_getdefault_multi()
|
||||||
old_value = values.getitem(slave, path,
|
old_value = values.getitem(slave, path, validate=False,
|
||||||
validate_properties=False)
|
validate_properties=False)
|
||||||
if len(old_value) < self.__len__():
|
if len(old_value) + 1 != self.__len__():
|
||||||
values.getitem(slave, path,
|
raise SlaveError(_("invalid len for the slave: {0}"
|
||||||
validate_properties=False).append(
|
" which has {1} as master").format(
|
||||||
dvalue, force=True)
|
self.opt._name, self.__len__()))
|
||||||
else:
|
values.getitem(slave, path, validate=False,
|
||||||
values.getitem(slave, path,
|
validate_properties=False).append(
|
||||||
validate_properties=False)[
|
dvalue, force=True)
|
||||||
index] = dvalue
|
|
||||||
|
|
||||||
def sort(self, cmp=None, key=None, reverse=False):
|
def sort(self, cmp=None, key=None, reverse=False):
|
||||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||||
|
@ -592,12 +591,12 @@ class Multi(list):
|
||||||
if self.opt.impl_get_multitype() == multitypes.slave:
|
if self.opt.impl_get_multitype() == multitypes.slave:
|
||||||
raise SlaveError(_("cannot pop a value on a multi option {0}"
|
raise SlaveError(_("cannot pop a value on a multi option {0}"
|
||||||
" which is a slave").format(self.opt._name))
|
" which is a slave").format(self.opt._name))
|
||||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
if self.opt.impl_get_multitype() == multitypes.master:
|
||||||
for slave in self.opt.impl_get_master_slaves():
|
for slave in self.opt.impl_get_master_slaves():
|
||||||
values = context.cfgimpl_get_values()
|
values = context.cfgimpl_get_values()
|
||||||
if not values.is_default_owner(slave):
|
if not values.is_default_owner(slave):
|
||||||
#get multi without valid properties
|
#get multi without valid properties
|
||||||
values.getitem(slave,
|
values.getitem(slave, validate=False,
|
||||||
validate_properties=False
|
validate_properties=False
|
||||||
).pop(index, force=True)
|
).pop(index, force=True)
|
||||||
#set value without valid properties
|
#set value without valid properties
|
||||||
|
|
Loading…
Reference in New Issue