key is now always path and change opt by path dictionary storage

This commit is contained in:
Emmanuel Garette 2013-08-21 22:21:50 +02:00
parent 707a215a2c
commit b6bb685ca5
12 changed files with 297 additions and 242 deletions

View File

@ -20,13 +20,13 @@ def test_cache():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u2 c.u2
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
assert od1.u2 in values._p_.get_cached('value', c) assert 'u2' in values._p_.get_cached('value', c)
assert od1.u2 in settings._p_.get_cached('property', c) assert 'u2' in settings._p_.get_cached('property', c)
def test_cache_reset(): def test_cache_reset():
@ -36,44 +36,44 @@ def test_cache_reset():
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value #when change a value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u2 = 1 c.u2 = 1
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when remove a value #when remove a value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
del(c.u2) del(c.u2)
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when add/del property #when add/del property
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings()[od1.u2].append('test') c.cfgimpl_get_settings()[od1.u2].append('test')
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings()[od1.u2].remove('test') c.cfgimpl_get_settings()[od1.u2].remove('test')
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when enable/disabled property #when enable/disabled property
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings().append('test') c.cfgimpl_get_settings().append('test')
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings().remove('test') c.cfgimpl_get_settings().remove('test')
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
def test_cache_reset_multi(): def test_cache_reset_multi():
@ -83,32 +83,32 @@ def test_cache_reset_multi():
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value #when change a value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u3 = [1] c.u3 = [1]
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when append value #when append value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u3.append(1) c.u3.append(1)
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when pop value #when pop value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u3.pop(1) c.u3.pop(1)
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
#when remove a value #when remove a value
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
del(c.u3) del(c.u3)
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
def test_reset_cache(): def test_reset_cache():
@ -117,23 +117,23 @@ def test_reset_cache():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache() c.cfgimpl_reset_cache()
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
c.u1 c.u1
sleep(1) sleep(1)
c.u2 c.u2
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
assert od1.u2 in values._p_.get_cached('value', c) assert 'u2' in values._p_.get_cached('value', c)
assert od1.u2 in settings._p_.get_cached('property', c) assert 'u2' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache() c.cfgimpl_reset_cache()
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
assert od1.u2 not in values._p_.get_cached('value', c) assert 'u2' not in values._p_.get_cached('value', c)
assert od1.u2 not in settings._p_.get_cached('property', c) assert 'u2' not in settings._p_.get_cached('property', c)
def test_reset_cache_only_expired(): def test_reset_cache_only_expired():
@ -142,22 +142,22 @@ def test_reset_cache_only_expired():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(True) c.cfgimpl_reset_cache(True)
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
sleep(1) sleep(1)
c.u2 c.u2
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
assert od1.u2 in values._p_.get_cached('value', c) assert 'u2' in values._p_.get_cached('value', c)
assert od1.u2 in settings._p_.get_cached('property', c) assert 'u2' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(True) c.cfgimpl_reset_cache(True)
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)
assert od1.u2 in values._p_.get_cached('value', c) assert 'u2' in values._p_.get_cached('value', c)
assert od1.u2 in settings._p_.get_cached('property', c) assert 'u2' in settings._p_.get_cached('property', c)
def test_reset_cache_only(): def test_reset_cache_only():
@ -166,14 +166,14 @@ def test_reset_cache_only():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(only=('values',)) c.cfgimpl_reset_cache(only=('values',))
assert od1.u1 not in values._p_.get_cached('value', c) assert 'u1' not in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 in settings._p_.get_cached('property', c) assert 'u1' in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(only=('settings',)) c.cfgimpl_reset_cache(only=('settings',))
assert od1.u1 in values._p_.get_cached('value', c) assert 'u1' in values._p_.get_cached('value', c)
assert od1.u1 not in settings._p_.get_cached('property', c) assert 'u1' not in settings._p_.get_cached('property', c)

View File

@ -39,6 +39,22 @@ def test_base_config():
assert dm._name == 'dummy' assert dm._name == 'dummy'
def test_base_path():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])
cfg = Config(descr)
assert cfg._impl_path is None
base = OptionDescription('config', '', [descr])
cfg = Config(base)
assert cfg._impl_path is None
assert cfg.tiramisu._impl_path == 'tiramisu'
nbase = OptionDescription('baseconfig', '', [base])
cfg = Config(nbase)
assert cfg._impl_path is None
assert cfg.config._impl_path == 'config'
assert cfg.config.tiramisu._impl_path == 'config.tiramisu'
def test_reset_value(): def test_reset_value():
descr = make_description() descr = make_description()
cfg = Config(descr) cfg = Config(descr)

View File

@ -164,3 +164,9 @@ def test_not_meta():
meta.set_contexts('od1.i1', 7) meta.set_contexts('od1.i1', 7)
assert conf1.od1.i1 == conf2.od1.i1 == 7 assert conf1.od1.i1 == conf2.od1.i1 == 7
assert conf1.getowner('od1.i1') is conf2.getowner('od1.i1') is owners.user assert conf1.getowner('od1.i1') is conf2.getowner('od1.i1') is owners.user
def test_meta_path():
meta = make_description()
assert meta._impl_path is None
assert meta.od1._impl_path == 'od1'

View File

@ -494,7 +494,7 @@ def test_callback_hidden():
od2 = OptionDescription('od2', '', [opt2]) od2 = OptionDescription('od2', '', [opt2])
maconfig = OptionDescription('rootconfig', '', [od1, od2]) maconfig = OptionDescription('rootconfig', '', [od1, od2])
cfg = Config(maconfig) cfg = Config(maconfig)
cfg.cfgimpl_get_settings().set_permissive(('hidden',)) cfg.cfgimpl_get_settings().setpermissive(('hidden',))
cfg.read_write() cfg.read_write()
raises(PropertiesOptionError, 'cfg.od1.opt1') raises(PropertiesOptionError, 'cfg.od1.opt1')
cfg.od2.opt2 cfg.od2.opt2

View File

@ -333,15 +333,15 @@ def test_reset_properties():
setting.reset() setting.reset()
assert setting._p_.get_properties(cfg) == {} assert setting._p_.get_properties(cfg) == {}
setting[option].append('test') setting[option].append('test')
assert setting._p_.get_properties(cfg) == {option: set(('test',))} assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
setting.reset() setting.reset()
assert setting._p_.get_properties(cfg) == {option: set(('test',))} assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
setting.append('frozen') setting.append('frozen')
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), 'gc.dummy': set(('test',))}
setting.reset(option) setting.reset(option)
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
setting[option].append('test') setting[option].append('test')
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), 'gc.dummy': set(('test',))}
setting.reset(all_properties=True) setting.reset(all_properties=True)
assert setting._p_.get_properties(cfg) == {} assert setting._p_.get_properties(cfg) == {}
raises(ValueError, 'setting.reset(all_properties=True, opt=option)') raises(ValueError, 'setting.reset(all_properties=True, opt=option)')

View File

@ -21,7 +21,7 @@ def test_permissive():
except PropertiesOptionError, err: except PropertiesOptionError, err:
props = err.proptype props = err.proptype
assert props == ['disabled'] assert props == ['disabled']
setting.set_permissive(('disabled',)) setting.setpermissive(('disabled',))
props = [] props = []
try: try:
config.u1 config.u1
@ -50,7 +50,7 @@ def test_permissive_mandatory():
except PropertiesOptionError, err: except PropertiesOptionError, err:
props = err.proptype props = err.proptype
assert props == ['disabled', 'mandatory'] assert props == ['disabled', 'mandatory']
setting.set_permissive(('mandatory', 'disabled',)) setting.setpermissive(('mandatory', 'disabled',))
setting.append('permissive') setting.append('permissive')
config.u1 config.u1
setting.remove('permissive') setting.remove('permissive')
@ -66,7 +66,7 @@ def test_permissive_frozen():
config = Config(descr) config = Config(descr)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
config.read_write() config.read_write()
setting.set_permissive(('frozen', 'disabled',)) setting.setpermissive(('frozen', 'disabled',))
try: try:
config.u1 = 1 config.u1 = 1
except PropertiesOptionError, err: except PropertiesOptionError, err:

View File

@ -35,15 +35,16 @@ def gen_id(config):
class SubConfig(BaseInformation): class SubConfig(BaseInformation):
"sub configuration management entry" "sub configuration management entry"
__slots__ = ('_impl_context', '_impl_descr') __slots__ = ('_impl_context', '_impl_descr', '_impl_path')
def __init__(self, descr, context): def __init__(self, descr, context, subpath=None):
""" Configuration option management master class """ Configuration option management master class
:param descr: describes the configuration schema :param descr: describes the configuration schema
:type descr: an instance of ``option.OptionDescription`` :type descr: an instance of ``option.OptionDescription``
:param context: the current root config :param context: the current root config
:type context: `Config` :type context: `Config`
:type subpath: `str` with the path name
""" """
# main option description # main option description
if not isinstance(descr, OptionDescription): if not isinstance(descr, OptionDescription):
@ -54,6 +55,7 @@ class SubConfig(BaseInformation):
if not isinstance(context, SubConfig): if not isinstance(context, SubConfig):
raise ValueError('context must be a SubConfig') raise ValueError('context must be a SubConfig')
self._impl_context = context self._impl_context = context
self._impl_path = subpath
def cfgimpl_reset_cache(self, only_expired=False, only=('values', def cfgimpl_reset_cache(self, only_expired=False, only=('values',
'settings')): 'settings')):
@ -183,7 +185,11 @@ class SubConfig(BaseInformation):
return homeconfig.__setattr__(name, value) return homeconfig.__setattr__(name, value)
child = getattr(self.cfgimpl_get_description(), name) child = getattr(self.cfgimpl_get_description(), name)
if not isinstance(child, SymLinkOption): if not isinstance(child, SymLinkOption):
self.cfgimpl_get_values().setitem(child, value, if self._impl_path is None:
path = name
else:
path = self._impl_path + '.' + name
self.cfgimpl_get_values().setitem(child, value, path,
force_permissive=force_permissive) force_permissive=force_permissive)
else: else:
context = self.cfgimpl_get_context() context = self.cfgimpl_get_context()
@ -193,7 +199,7 @@ class SubConfig(BaseInformation):
def __delattr__(self, name): def __delattr__(self, name):
child = getattr(self.cfgimpl_get_description(), name) child = getattr(self.cfgimpl_get_description(), name)
del(self.cfgimpl_get_values()[child]) self.cfgimpl_get_values().__delitem__(child)
def __getattr__(self, name): def __getattr__(self, name):
return self._getattr(name) return self._getattr(name)
@ -222,6 +228,10 @@ class SubConfig(BaseInformation):
return object.__getattribute__(self, name) return object.__getattribute__(self, name)
opt_or_descr = getattr(self.cfgimpl_get_description(), name) opt_or_descr = getattr(self.cfgimpl_get_description(), name)
# symlink options # symlink options
if self._impl_path is None:
subpath = name
else:
subpath = self._impl_path + '.' + name
if isinstance(opt_or_descr, SymLinkOption): if isinstance(opt_or_descr, SymLinkOption):
context = self.cfgimpl_get_context() context = self.cfgimpl_get_context()
path = context.cfgimpl_get_description().impl_get_path_by_opt( path = context.cfgimpl_get_description().impl_get_path_by_opt(
@ -231,12 +241,13 @@ class SubConfig(BaseInformation):
force_permissive=force_permissive) force_permissive=force_permissive)
elif isinstance(opt_or_descr, OptionDescription): elif isinstance(opt_or_descr, OptionDescription):
self.cfgimpl_get_settings().validate_properties( self.cfgimpl_get_settings().validate_properties(
opt_or_descr, True, False, force_permissive=force_permissive, opt_or_descr, True, False, path=subpath,
force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
return SubConfig(opt_or_descr, self.cfgimpl_get_context()) return SubConfig(opt_or_descr, self.cfgimpl_get_context(), subpath)
else: else:
return self.cfgimpl_get_values().getitem( return self.cfgimpl_get_values().getitem(
opt_or_descr, opt_or_descr, path=subpath,
validate=validate, validate=validate,
force_properties=force_properties, force_properties=force_properties,
force_permissive=force_permissive) force_permissive=force_permissive)
@ -555,6 +566,7 @@ class MetaConfig(CommonConfig):
if not isinstance(children, list): if not isinstance(children, list):
raise ValueError(_("metaconfig's children must be a list")) raise ValueError(_("metaconfig's children must be a list"))
self._impl_descr = None self._impl_descr = None
self._impl_path = None
if meta: if meta:
for child in children: for child in children:
if not isinstance(child, CommonConfig): if not isinstance(child, CommonConfig):

View File

@ -152,24 +152,25 @@ populate_multitypes()
class Property(object): class Property(object):
"a property is responsible of the option's value access rules" "a property is responsible of the option's value access rules"
__slots__ = ('_setting', '_properties', '_opt') __slots__ = ('_setting', '_properties', '_opt', '_path')
def __init__(self, setting, prop, opt=None): def __init__(self, setting, prop, opt=None, path=None):
self._opt = opt self._opt = opt
self._path = path
self._setting = setting self._setting = setting
self._properties = prop self._properties = prop
def append(self, propname): def append(self, propname):
self._properties.add(propname) self._properties.add(propname)
self._setting._setproperties(self._properties, self._opt) self._setting._setproperties(self._properties, self._opt, self._path)
def remove(self, propname): def remove(self, propname):
if propname in self._properties: if propname in self._properties:
self._properties.remove(propname) self._properties.remove(propname)
self._setting._setproperties(self._properties, self._opt) self._setting._setproperties(self._properties, self._opt, self._path)
def reset(self): def reset(self):
self._setting.reset(opt=self._opt) self._setting.reset(path=self._path)
def __contains__(self, propname): def __contains__(self, propname):
return propname in self._properties return propname in self._properties
@ -200,15 +201,6 @@ class Settings(object):
self._p_ = __import__(import_lib, globals(), locals(), ['Settings'], self._p_ = __import__(import_lib, globals(), locals(), ['Settings'],
-1).Settings(storage) -1).Settings(storage)
def _getkey(self, opt):
if self._p_.key_is_path:
if opt is None:
return '_none'
else:
return self._get_opt_path(opt)
else:
return opt
#____________________________________________________________ #____________________________________________________________
# properties methods # properties methods
def __contains__(self, propname): def __contains__(self, propname):
@ -219,7 +211,14 @@ class Settings(object):
return str(list(self._getproperties())) return str(list(self._getproperties()))
def __getitem__(self, opt): def __getitem__(self, opt):
return Property(self, self._getproperties(opt), opt) if opt is None:
path = None
else:
path = self._get_opt_path(opt)
return self._getitem(opt, path)
def _getitem(self, opt, path):
return Property(self, self._getproperties(opt, path), opt, path)
def __setitem__(self, opt, value): def __setitem__(self, opt, value):
raise ValueError('you must only append/remove properties') raise ValueError('you must only append/remove properties')
@ -231,26 +230,32 @@ class Settings(object):
if all_properties: if all_properties:
self._p_.reset_all_propertives() self._p_.reset_all_propertives()
else: else:
self._p_.reset_properties(self._getkey(opt)) if opt is None:
path = None
else:
path = self._get_opt_path(opt)
self._p_.reset_properties(path)
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
def _getproperties(self, opt=None, is_apply_req=True): def _getproperties(self, opt=None, path=None, is_apply_req=True):
if opt is None: if opt is None:
props = self._p_.getproperties(self._getkey(opt), default_properties) props = self._p_.getproperties(path, default_properties)
else: else:
if path is None:
raise ValueError(_('if opt is not None, path should not be None in _getproperties'))
ntime = None ntime = None
if self._p_.hascache('property', self._getkey(opt)): if self._p_.hascache('property', path):
ntime = time() ntime = time()
is_cached, props = self._p_.getcache('property', self._getkey(opt), ntime) is_cached, props = self._p_.getcache('property', path, ntime)
if is_cached: if is_cached:
return props return props
if is_apply_req: if is_apply_req:
self.apply_requires(opt) self.apply_requires(opt, path)
props = self._p_.getproperties(self._getkey(opt), opt._properties) props = self._p_.getproperties(path, opt._properties)
if 'expire' in self: if 'expire' in self:
if ntime is None: if ntime is None:
ntime = time() ntime = time()
self._p_.setcache('property', self._getkey(opt), props, ntime + expires_time) self._p_.setcache('property', path, props, ntime + expires_time)
return props return props
def append(self, propname): def append(self, propname):
@ -261,21 +266,21 @@ class Settings(object):
"deletes property propname in the Config's properties attribute" "deletes property propname in the Config's properties attribute"
Property(self, self._getproperties()).remove(propname) Property(self, self._getproperties()).remove(propname)
def _setproperties(self, properties, opt=None): def _setproperties(self, properties, opt, path):
"""save properties for specified opt """save properties for specified opt
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
if opt is None: if opt is None:
self._p_.setproperties(self._getkey(opt), properties) self._p_.setproperties(path, properties)
else: else:
if set(opt._properties) == properties: if set(opt._properties) == properties:
self._p_.reset_properties(self._getkey(opt)) self._p_.reset_properties(path)
else: else:
self._p_.setproperties(self._getkey(opt), properties) self._p_.setproperties(path, properties)
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
#____________________________________________________________ #____________________________________________________________
def validate_properties(self, opt_or_descr, is_descr, is_write, def validate_properties(self, opt_or_descr, is_descr, is_write, path,
value=None, force_permissive=False, value=None, force_permissive=False,
force_properties=None): force_properties=None):
""" """
@ -291,9 +296,9 @@ class Settings(object):
property) property)
""" """
# opt properties # opt properties
properties = copy(self._getproperties(opt_or_descr)) properties = copy(self._getproperties(opt_or_descr, path))
# remove opt permissive # remove opt permissive
properties -= self._p_.getpermissive(self._getkey(opt_or_descr)) properties -= self._p_.getpermissive(path)
# remove global permissive if need # remove global permissive if need
self_properties = copy(self._getproperties()) self_properties = copy(self._getproperties())
if force_permissive is True or 'permissive' in self_properties: if force_permissive is True or 'permissive' in self_properties:
@ -332,11 +337,10 @@ class Settings(object):
"").format(opt_or_descr._name, "").format(opt_or_descr._name,
str(props)), props) str(props)), props)
# XXX should rename it to setpermissive, but kept for retro compatibility def setpermissive(self, permissive, path=None):
def set_permissive(self, permissive, opt=None):
if not isinstance(permissive, tuple): if not isinstance(permissive, tuple):
raise TypeError(_('permissive must be a tuple')) raise TypeError(_('permissive must be a tuple'))
self._p_.setpermissive(self._getkey(opt), permissive) self._p_.setpermissive(path, permissive)
#____________________________________________________________ #____________________________________________________________
def setowner(self, owner): def setowner(self, owner):
@ -369,28 +373,27 @@ class Settings(object):
else: else:
self._p_.reset_all_cache('property') self._p_.reset_all_cache('property')
def apply_requires(self, opt): def apply_requires(self, opt, path):
"carries out the jit (just in time requirements between options" "carries out the jit (just in time requirements between options"
if opt._requires is None: if opt._requires is None:
return return
# filters the callbacks # filters the callbacks
setting = Property(self, self._getproperties(opt, False), opt) setting = Property(self, self._getproperties(opt, path, False), opt, path=path)
descr = self.context.cfgimpl_get_description() descr = self.context.cfgimpl_get_description()
optpath = descr.impl_get_path_by_opt(opt)
for requires in opt._requires: for requires in opt._requires:
matches = False matches = False
for require in requires: for require in requires:
option, expected, action, inverse, \ option, expected, action, inverse, \
transitive, same_action = require transitive, same_action = require
path = descr.impl_get_path_by_opt(option) reqpath = self._get_opt_path(option)
if path == optpath or path.startswith(optpath + '.'): if reqpath == path or reqpath.startswith(path + '.'):
raise RequirementError(_("malformed requirements " raise RequirementError(_("malformed requirements "
"imbrication detected for option:" "imbrication detected for option:"
" '{0}' with requirement on: " " '{0}' with requirement on: "
"'{1}'").format(optpath, path)) "'{1}'").format(path, reqpath))
try: try:
value = self.context._getattr(path, force_permissive=True) value = self.context._getattr(reqpath, force_permissive=True)
except PropertiesOptionError, err: except PropertiesOptionError, err:
if not transitive: if not transitive:
continue continue
@ -400,14 +403,14 @@ class Settings(object):
"requirement's property " "requirement's property "
"error: " "error: "
"{1} {2}").format(opt._name, "{1} {2}").format(opt._name,
path, reqpath,
properties)) properties))
# transitive action, force expected # transitive action, force expected
value = expected[0] value = expected[0]
inverse = False inverse = False
except AttributeError: except AttributeError:
raise AttributeError(_("required option not found: " raise AttributeError(_("required option not found: "
"{0}").format(path)) "{0}").format(reqpath))
if (not inverse and if (not inverse and
value in expected or value in expected or
inverse and value not in expected): inverse and value not in expected):

View File

@ -32,21 +32,21 @@ class Settings(Cache):
super(Settings, self).__init__() super(Settings, self).__init__()
# propertives # propertives
def setproperties(self, opt, properties): def setproperties(self, path, properties):
self._properties[opt] = properties self._properties[path] = properties
def getproperties(self, opt, default_properties): def getproperties(self, path, default_properties):
return self._properties.get(opt, set(default_properties)) return self._properties.get(path, set(default_properties))
def hasproperties(self, opt): def hasproperties(self, path):
return opt in self._properties return path in self._properties
def reset_all_propertives(self): def reset_all_propertives(self):
self._properties.clear() self._properties.clear()
def reset_properties(self, opt): def reset_properties(self, path):
try: try:
del(self._properties[opt]) del(self._properties[path])
except KeyError: except KeyError:
pass pass
@ -54,8 +54,8 @@ class Settings(Cache):
return self._properties return self._properties
# permissive # permissive
def setpermissive(self, opt, permissive): def setpermissive(self, path, permissive):
self._permissives[opt] = frozenset(permissive) self._permissives[path] = frozenset(permissive)
def getpermissive(self, opt=None): def getpermissive(self, path=None):
return self._permissives.get(opt, frozenset()) return self._permissives.get(path, frozenset())

View File

@ -36,22 +36,22 @@ class Cache(object):
def __init__(self): def __init__(self):
self._cache = {} self._cache = {}
def setcache(self, cache_type, opt, val, time): def setcache(self, cache_type, path, val, time):
self._cache[opt] = (val, time) self._cache[path] = (val, time)
def getcache(self, cache_type, opt, exp): def getcache(self, cache_type, path, exp):
value, created = self._cache[opt] value, created = self._cache[path]
if exp < created: if exp < created:
return True, value return True, value
return False, None return False, None
def hascache(self, cache_type, opt): def hascache(self, cache_type, path):
""" option is in the cache """ path is in the cache
:param cache_type: value | property :param cache_type: value | property
:param opt: the key (typically, the option object) :param path: the path's option
""" """
return opt in self._cache return path in self._cache
def reset_expired_cache(self, cache_type, exp): def reset_expired_cache(self, cache_type, exp):
keys = self._cache.keys() keys = self._cache.keys()
@ -66,6 +66,6 @@ class Cache(object):
def get_cached(self, cache_type, context): def get_cached(self, cache_type, context):
"""return all values in a dictionary """return all values in a dictionary
example: {option1: ('value1', 'time1'), option2: ('value2', 'time2')} example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
""" """
return self._cache return self._cache

View File

@ -32,43 +32,43 @@ class Values(Cache):
super(Values, self).__init__() super(Values, self).__init__()
# value # value
def setvalue(self, opt, value, owner): def setvalue(self, path, value, owner):
"""set value for an option """set value for a path
a specified value must be associated to an owner a specified value must be associated to an owner
""" """
self._values[opt] = (owner, value) self._values[path] = (owner, value)
def getvalue(self, opt): def getvalue(self, path):
"""get value for an option """get value for a path
return: only value, not the owner return: only value, not the owner
""" """
return self._values[opt][1] return self._values[path][1]
def hasvalue(self, opt): def hasvalue(self, path):
"""if opt has a value """if path has a value
return: boolean return: boolean
""" """
return opt in self._values return path in self._values
def resetvalue(self, opt): def resetvalue(self, path):
"""remove value means delete value in storage """remove value means delete value in storage
""" """
del(self._values[opt]) del(self._values[path])
def get_modified_values(self): def get_modified_values(self):
"""return all values in a dictionary """return all values in a dictionary
example: {option1: (owner, 'value1'), option2: (owner, 'value2')} example: {'path1': (owner, 'value1'), 'path2': (owner, 'value2')}
""" """
return self._values return self._values
# owner # owner
def setowner(self, opt, owner): def setowner(self, path, owner):
"""change owner for an option """change owner for a path
""" """
self._values[opt] = (owner, self._values[opt][1]) self._values[path] = (owner, self._values[path][1])
def getowner(self, opt, default): def getowner(self, path, default):
"""get owner for an option """get owner for a path
return: owner object return: owner object
""" """
return self._values.get(opt, (default, None))[0] return self._values.get(path, (default, None))[0]

View File

@ -46,15 +46,6 @@ class Values(object):
self._p_ = __import__(import_lib, globals(), locals(), ['Values'], self._p_ = __import__(import_lib, globals(), locals(), ['Values'],
-1).Values(storage) -1).Values(storage)
def _getkey(self, opt):
"""depends on the storage utility.
typically, the option's path in the parent `Config` or `SubConfig`
"""
if self._p_.key_is_path:
return self._get_opt_path(opt)
else:
return opt
def _getdefault(self, opt): def _getdefault(self, opt):
""" """
actually retrieves the default value actually retrieves the default value
@ -71,24 +62,23 @@ class Values(object):
else: else:
return value return value
def _getvalue(self, opt, validate=True): def _getvalue(self, opt, path, validate=True):
"""actually retrieves the value """actually retrieves the value
:param opt: the `option.Option()` object :param opt: the `option.Option()` object
:returns: the option's value (or the default value if not set) :returns: the option's value (or the default value if not set)
""" """
key = self._getkey(opt) if not self._p_.hasvalue(path):
if not self._p_.hasvalue(key):
# if there is no value # if there is no value
value = self._getdefault(opt) value = self._getdefault(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, path, validate)
else: else:
# if there is a value # if there is a value
value = self._p_.getvalue(key) value = self._p_.getvalue(path)
if opt.impl_is_multi() and not isinstance(value, Multi): if opt.impl_is_multi() and not isinstance(value, Multi):
# load value so don't need to validate if is not a Multi # load value so don't need to validate if is not a Multi
value = Multi(value, self.context, opt, validate=False) value = Multi(value, self.context, opt, path, validate=False)
return value return value
def get_modified_values(self): def get_modified_values(self):
@ -101,15 +91,20 @@ class Values(object):
:param opt: the `option.Option()` object :param opt: the `option.Option()` object
""" """
return self._p_.hasvalue('value', self._getkey(opt)) path = self._get_opt_path(opt)
self._contains(path)
def _contains(self, path):
return self._p_.hasvalue('value', path)
def __delitem__(self, opt): def __delitem__(self, opt):
"""overrides the builtins `del()` instructions""" """overrides the builtins `del()` instructions"""
self.reset(opt) self.reset(opt)
def reset(self, opt): def reset(self, opt, path=None):
key = self._getkey(opt) if path is None:
if self._p_.hasvalue(key): path = self._get_opt_path(opt)
if self._p_.hasvalue(path):
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
opt.impl_validate(opt.impl_getdefault(), self.context, opt.impl_validate(opt.impl_getdefault(), self.context,
'validator' in setting) 'validator' in setting)
@ -118,7 +113,7 @@ class Values(object):
opt.impl_get_multitype() == multitypes.master): opt.impl_get_multitype() == multitypes.master):
for slave in opt.impl_get_master_slaves(): for slave in opt.impl_get_master_slaves():
self.reset(slave) self.reset(slave)
self._p_.resetvalue(key) self._p_.resetvalue(path)
def _isempty(self, opt, value): def _isempty(self, opt, value):
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
@ -150,30 +145,31 @@ class Values(object):
"enables us to use the pythonic dictionnary-like access to values" "enables us to use the pythonic dictionnary-like access to values"
return self.getitem(opt) return self.getitem(opt)
def getitem(self, opt, validate=True, force_permissive=False, def getitem(self, opt, path=None, validate=True, force_permissive=False,
force_properties=None, validate_properties=True): force_properties=None, validate_properties=True):
ntime = None ntime = None
key = self._getkey(opt) if path is None:
if self._p_.hascache('value', self._getkey(opt)): path = self._get_opt_path(opt)
if self._p_.hascache('value', path):
ntime = time() ntime = time()
is_cached, value = self._p_.getcache('value', key, ntime) is_cached, value = self._p_.getcache('value', path, ntime)
if is_cached: if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi): if opt.impl_is_multi() and not isinstance(value, Multi):
#load value so don't need to validate if is not a Multi #load value so don't need to validate if is not a Multi
value = Multi(value, self.context, opt, validate=False) value = Multi(value, self.context, opt, path, validate=False)
return value return value
val = self._getitem(opt, validate, force_permissive, force_properties, val = self._getitem(opt, path, validate, force_permissive, force_properties,
validate_properties) validate_properties)
if 'expire' in self.context.cfgimpl_get_settings() and validate and \ if 'expire' in self.context.cfgimpl_get_settings() and validate and \
validate_properties and force_permissive is False and \ validate_properties and force_permissive is False and \
force_properties is None: force_properties is None:
if ntime is None: if ntime is None:
ntime = time() ntime = time()
self._p_.setcache('value', key, val, ntime + expires_time) self._p_.setcache('value', path, val, ntime + expires_time)
return val return val
def _getitem(self, opt, validate, force_permissive, force_properties, def _getitem(self, opt, path, validate, force_permissive, force_properties,
validate_properties): validate_properties):
# options with callbacks # options with callbacks
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
@ -181,7 +177,7 @@ class Values(object):
# if value is callback and is not set # if value is 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(opt) or self._is_default_owner(path) or
(is_frozen and 'force_default_on_freeze' in setting[opt])): (is_frozen and 'force_default_on_freeze' in setting[opt])):
no_value_slave = False no_value_slave = False
if (opt.impl_is_multi() and if (opt.impl_is_multi() and
@ -200,53 +196,55 @@ class Values(object):
if not isinstance(value, list): if not isinstance(value, list):
value = [value for i in range(lenmaster)] value = [value for i in range(lenmaster)]
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, path, validate)
# suppress value if already set # suppress value if already set
self.reset(opt) self.reset(opt, path)
# frozen and force default # frozen and force default
elif is_frozen and 'force_default_on_freeze' in setting[opt]: elif is_frozen and 'force_default_on_freeze' in setting[opt]:
value = self._getdefault(opt) value = self._getdefault(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, path, validate)
else: else:
value = self._getvalue(opt, validate) value = self._getvalue(opt, path, validate)
if validate: if validate:
opt.impl_validate(value, self.context, 'validator' in setting) opt.impl_validate(value, self.context, 'validator' in setting)
if self.is_default_owner(opt) and \ if self._is_default_owner(path) and \
'force_store_value' in setting[opt]: 'force_store_value' in setting[opt]:
self.setitem(opt, value, is_write=False) self.setitem(opt, value, path, is_write=False)
if validate_properties: if validate_properties:
setting.validate_properties(opt, False, False, value=value, setting.validate_properties(opt, False, False, value=value, path=path,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
return value return value
def __setitem__(self, opt, value): def __setitem__(self, opt, value):
self.setitem(opt, value) path = self._get_opt_path(opt)
self.setitem(opt, value, path)
def setitem(self, opt, value, force_permissive=False, is_write=True): def setitem(self, opt, value, path, force_permissive=False,
is_write=True):
# is_write is, for example, used with "force_store_value" # is_write is, for example, used with "force_store_value"
# user didn't change value, so not write # user didn't change value, so not write
# valid opt # valid opt
opt.impl_validate(value, self.context, opt.impl_validate(value, self.context,
'validator' in self.context.cfgimpl_get_settings()) 'validator' in self.context.cfgimpl_get_settings())
if opt.impl_is_multi() and not isinstance(value, Multi): if opt.impl_is_multi() and not isinstance(value, Multi):
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt, path)
self._setvalue(opt, value, force_permissive=force_permissive, self._setvalue(opt, path, value, force_permissive=force_permissive,
is_write=is_write) is_write=is_write)
def _setvalue(self, opt, value, force_permissive=False, def _setvalue(self, opt, path, value, force_permissive=False,
force_properties=None, force_properties=None,
is_write=True, validate_properties=True): is_write=True, validate_properties=True):
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
if validate_properties: if validate_properties:
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
setting.validate_properties(opt, False, is_write, setting.validate_properties(opt, False, is_write,
value=value, value=value, path=path,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
owner = self.context.cfgimpl_get_settings().getowner() owner = self.context.cfgimpl_get_settings().getowner()
self._p_.setvalue(self._getkey(opt), value, owner) self._p_.setvalue(path, value, owner)
def getowner(self, opt): def getowner(self, opt):
""" """
@ -257,10 +255,14 @@ class Values(object):
""" """
if isinstance(opt, SymLinkOption): if isinstance(opt, SymLinkOption):
opt = opt._opt opt = opt._opt
owner = self._p_.getowner(self._getkey(opt), owners.default) path = self._get_opt_path(opt)
return self._getowner(path)
def _getowner(self, path):
owner = self._p_.getowner(path, owners.default)
meta = self.context.cfgimpl_get_meta() meta = self.context.cfgimpl_get_meta()
if owner is owners.default and meta is not None: if owner is owners.default and meta is not None:
owner = meta.cfgimpl_get_values().getowner(opt) owner = meta.cfgimpl_get_values()._getowner(path)
return owner return owner
def setowner(self, opt, owner): def setowner(self, opt, owner):
@ -272,10 +274,15 @@ class Values(object):
""" """
if not isinstance(owner, owners.Owner): if not isinstance(owner, owners.Owner):
raise TypeError(_("invalid generic owner {0}").format(str(owner))) raise TypeError(_("invalid generic owner {0}").format(str(owner)))
if self.getowner(opt) == owners.default:
path = self._get_opt_path(opt)
self._setowner(path, owner)
def _setowner(self, path, owner):
if self._getowner(path) == owners.default:
raise ConfigError(_('no value for {0} cannot change owner to {1}' raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(opt._name, owner)) '').format(path, owner))
self._p_.setowner(self._getkey(opt), owner) self._p_.setowner(path, owner)
def is_default_owner(self, opt): def is_default_owner(self, opt):
""" """
@ -283,7 +290,11 @@ class Values(object):
(not the toplevel config) (not the toplevel config)
:return: boolean :return: boolean
""" """
return self.getowner(opt) == owners.default path = self._get_opt_path(opt)
return self._is_default_owner(path)
def _is_default_owner(self, path):
return self._getowner(path) == owners.default
def reset_cache(self, only_expired): def reset_cache(self, only_expired):
""" """
@ -310,15 +321,16 @@ class Values(object):
class Multi(list): class Multi(list):
"""multi options values container """multi options values container
that support item notation for the values of multi options""" that support item notation for the values of multi options"""
__slots__ = ('opt', 'context') __slots__ = ('opt', 'path', 'context')
def __init__(self, value, context, opt, validate=True): def __init__(self, value, context, opt, path, validate=True):
""" """
:param value: the Multi wraps a list value :param value: the Multi wraps a list value
:param context: the home config that has the values :param context: the home config that has the values
:param opt: the option object that have this Multi value :param opt: the option object that have this Multi value
""" """
self.opt = opt self.opt = opt
self.path = path
self.context = context self.context = context
if not isinstance(value, list): if not isinstance(value, list):
value = [value] value = [value]
@ -337,7 +349,7 @@ class Multi(list):
valuelen = len(value) valuelen = len(value)
if valuelen > masterlen or (valuelen < masterlen and if valuelen > masterlen or (valuelen < masterlen and
not self.context.cfgimpl_get_values( not self.context.cfgimpl_get_values(
).is_default_owner(self.opt)): )._is_default_owner(self.path)):
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))
@ -351,8 +363,9 @@ class Multi(list):
masterlen = len(value) masterlen = len(value)
values = self.context.cfgimpl_get_values() values = self.context.cfgimpl_get_values()
for slave in self.opt._master_slaves: for slave in self.opt._master_slaves:
if not values.is_default_owner(slave): path = values._get_opt_path(slave)
value_slave = values._getvalue(slave) if not values._is_default_owner(path):
value_slave = values._getvalue(slave, path)
if len(value_slave) > masterlen: if len(value_slave) > masterlen:
raise SlaveError(_("invalid len for the master: {0}" raise SlaveError(_("invalid len for the master: {0}"
" which has {1} as slave with" " which has {1} as slave with"
@ -363,11 +376,11 @@ class Multi(list):
value_slave.append(slave.impl_getdefault_multi(), value_slave.append(slave.impl_getdefault_multi(),
force=True) force=True)
def __setitem__(self, key, value): def __setitem__(self, path, value):
self._validate(value) self._validate(value)
#assume not checking mandatory property #assume not checking mandatory property
super(Multi, self).__setitem__(key, value) super(Multi, self).__setitem__(path, value)
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, path, self)
def append(self, value, force=False): def append(self, value, force=False):
"""the list value can be updated (appened) """the list value can be updated (appened)
@ -386,21 +399,26 @@ class Multi(list):
value = None value = None
self._validate(value) self._validate(value)
super(Multi, self).append(value) super(Multi, self).append(value)
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
if not force and self.opt.impl_get_multitype() == multitypes.master: if not force and 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():
if not values.is_default_owner(slave): path = values._get_opt_path(slave)
if not values._is_default_owner(path):
if slave.impl_has_callback(): if slave.impl_has_callback():
index = self.__len__() - 1 index = self.__len__() - 1
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, validate_properties=False) old_value = values.getitem(slave, path,
validate_properties=False)
if len(old_value) < self.__len__(): if len(old_value) < self.__len__():
values.getitem(slave, validate_properties=False).append( values.getitem(slave, path,
validate_properties=False).append(
dvalue, force=True) dvalue, force=True)
else: else:
values.getitem(slave, validate_properties=False)[index] = dvalue values.getitem(slave, path,
validate_properties=False)[
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,
@ -408,7 +426,7 @@ class Multi(list):
raise SlaveError(_("cannot sort multi option {0} if master or slave" raise SlaveError(_("cannot sort multi option {0} if master or slave"
"").format(self.opt._name)) "").format(self.opt._name))
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse) super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
def reverse(self): def reverse(self):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
@ -416,7 +434,7 @@ class Multi(list):
raise SlaveError(_("cannot reverse multi option {0} if master or " raise SlaveError(_("cannot reverse multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
super(Multi, self).reverse() super(Multi, self).reverse()
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
def insert(self, index, obj): def insert(self, index, obj):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
@ -424,7 +442,7 @@ class Multi(list):
raise SlaveError(_("cannot insert multi option {0} if master or " raise SlaveError(_("cannot insert multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
super(Multi, self).insert(index, obj) super(Multi, self).insert(index, obj)
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
def extend(self, iterable): def extend(self, iterable):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
@ -432,7 +450,7 @@ class Multi(list):
raise SlaveError(_("cannot extend multi option {0} if master or " raise SlaveError(_("cannot extend multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
super(Multi, self).extend(iterable) super(Multi, self).extend(iterable)
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
def _validate(self, value): def _validate(self, value):
if value is not None: if value is not None:
@ -465,5 +483,5 @@ class Multi(list):
).pop(key, force=True) ).pop(key, force=True)
#set value without valid properties #set value without valid properties
ret = super(Multi, self).pop(key) ret = super(Multi, self).pop(key)
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force) self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
return ret return ret