requires could be apply to a slave and properties could be different

This commit is contained in:
Emmanuel Garette 2015-11-29 23:03:08 +01:00
parent c2a6772ec2
commit a521a6d322
20 changed files with 403 additions and 241 deletions

View File

@ -1,3 +1,6 @@
Sun Nov 29 23:01:28 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* requires could be apply to a slave and properties could be different
Mon Oct 12 17:05:28 2015 +0200 Emmanuel Garette <egarette@cadoles.com> Mon Oct 12 17:05:28 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* domainname with only one character is now allowed * domainname with only one character is now allowed

View File

@ -4,9 +4,10 @@ do_autopath()
from tiramisu import setting from tiramisu import setting
setting.expires_time = 1 setting.expires_time = 1
from tiramisu.option import IntOption, OptionDescription from tiramisu.option import IntOption, StrOption, OptionDescription
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.error import ConfigError, PropertiesOptionError from tiramisu.error import ConfigError
from tiramisu.setting import groups
from time import sleep, time from time import sleep, time
@ -50,9 +51,9 @@ def test_get_cache():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
ntime = time() + 1 ntime = time() + 1
settings._p_.setcache('u1', set(['inject']), ntime) settings._p_.setcache('u1', set(['inject']), ntime, None)
assert 'inject' in settings[od1.u1] assert 'inject' in settings[od1.u1]
values._p_.setcache('u1', 100, ntime) values._p_.setcache('u1', 100, ntime, None)
assert c.u1 == [100] assert c.u1 == [100]
@ -62,9 +63,9 @@ def test_get_cache_no_expire():
c = Config(od1) c = Config(od1)
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
settings._p_.setcache('u1', set(['inject2']), None) settings._p_.setcache('u1', set(['inject2']), None, None)
assert 'inject2' in settings[od1.u1] assert 'inject2' in settings[od1.u1]
values._p_.setcache('u1', 200, None) values._p_.setcache('u1', 200, None, None)
assert c.u1 == [200] assert c.u1 == [200]
@ -279,13 +280,70 @@ def test_force_cache():
c.cfgimpl_get_settings().remove('expire') c.cfgimpl_get_settings().remove('expire')
c.cfgimpl_get_values().force_cache() c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None), 'u4': (None, None)} assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)},
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)} 'u2': {None: (None, None)},
'u3': {None: ([], None)},
'u4': {None: (None, None)}}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
'u2': {None: (set([]), None)},
'u3': {None: (set([]), None)},
'u4': {None: (set(['disabled']), None)}}
c.read_only() c.read_only()
c.cfgimpl_get_values().force_cache() c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None)} assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)},
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)} 'u2': {None: (None, None)},
'u3': {None: ([], None)}}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
'u2': {None: (set([]), None)},
'u3': {None: (set([]), None)},
'u4': {None: (set(['disabled']), None)}}
c.cfgimpl_get_settings().remove('cache') c.cfgimpl_get_settings().remove('cache')
raises(ConfigError, "c.cfgimpl_get_values().force_cache()") raises(ConfigError, "c.cfgimpl_get_values().force_cache()")
def test_cache_master_slave():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {}
#
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
cfg.ip_admin_eth0.ip_admin_eth0
cfg.ip_admin_eth0.netmask_admin_eth0
cache = cfg.cfgimpl_get_values()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2']
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0])
assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None]
assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
cache = cfg.cfgimpl_get_settings()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0])
#
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
cfg.ip_admin_eth0.ip_admin_eth0
cfg.ip_admin_eth0.netmask_admin_eth0
cache = cfg.cfgimpl_get_values()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2', '192.168.1.1']
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None, None]
assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None
cache = cfg.cfgimpl_get_settings()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
#DEL, insert, ...

View File

@ -102,6 +102,24 @@ def test_make_dict_with_disabled():
OptionDescription("s1", "", [ OptionDescription("s1", "", [
BoolOption("a", "", default=False), BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('disabled',))]), BoolOption("b", "", default=False, properties=('disabled',))]),
OptionDescription("s2", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False)], properties=('disabled',)),
IntOption("int", "", default=42)])
config = Config(descr)
config.read_only()
d = config.make_dict()
assert d == {"s1.a": False, "int": 42}
def test_make_dict_with_disabled_in_callback():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('disabled',))]),
OptionDescription("s2", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False)], properties=('disabled',)),
IntOption("int", "", default=42)]) IntOption("int", "", default=42)])
config = Config(descr) config = Config(descr)
config.read_only() config.read_only()

View File

@ -4,7 +4,7 @@ do_autopath()
from py.test import raises from py.test import raises
from tiramisu.setting import owners from tiramisu.setting import owners, groups
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \ from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription StrOption, OptionDescription
@ -96,6 +96,7 @@ def test_default_with_multi():
def test_idontexist(): def test_idontexist():
descr = make_description() descr = make_description()
cfg = Config(descr) cfg = Config(descr)
cfg
raises(AttributeError, "cfg.idontexist") raises(AttributeError, "cfg.idontexist")
@ -222,9 +223,50 @@ def test_multi_with_requires_with_disabled_in_another_group():
def test_multi_with_requires_that_is_multi(): def test_multi_with_requires_that_is_multi():
s = StrOption("string", "", default=["string"], multi=True) b = IntOption('int', 'Test int option', default=[0], multi=True)
intoption = IntOption('int', 'Test int option', default=[0], multi=True) c = StrOption('str', 'Test string option', default=['abc'], requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
raises(ValueError, "StrOption('str', 'Test string option', default=['abc'], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True)") descr = OptionDescription("opt", "", [b, c])
descr
raises(ValueError, "Config(descr)")
def test_multi_with_requires_that_is_masterslave():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = OptionDescription("int", "", [b, c])
descr.impl_set_group_type(groups.master)
Config(descr)
def test_multi_with_requires_that_is_masterslave_master():
b = IntOption('int', 'Test int option', multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = OptionDescription("str", "", [c, b])
descr.impl_set_group_type(groups.master)
raises(ValueError, "Config(descr)")
def test_multi_with_requires_that_is_masterslave2():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', multi=True)
d = StrOption('str1', 'Test string option', requires=[{'option': c, 'expected': '1', 'action': 'hidden'}], multi=True)
descr = OptionDescription("int", "", [b, c, d])
descr.impl_set_group_type(groups.master)
Config(descr)
def test_multi_with_requires_that_is_not_same_masterslave():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr1 = OptionDescription("int", "", [b, c])
descr1.impl_set_group_type(groups.master)
d = IntOption('int1', 'Test int option', default=[0], multi=True)
e = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr2 = OptionDescription("int1", "", [d, e])
descr2.impl_set_group_type(groups.master)
descr3 = OptionDescription('val', '', [descr1, descr2])
descr3
raises(ValueError, "Config(descr3)")
def test_multi_with_bool(): def test_multi_with_bool():
@ -241,6 +283,7 @@ def test_multi_with_bool_two():
s = BoolOption("bool", "", default=[False], multi=True) s = BoolOption("bool", "", default=[False], multi=True)
descr = OptionDescription("options", "", [s]) descr = OptionDescription("options", "", [s])
config = Config(descr) config = Config(descr)
config
assert descr.bool.impl_is_multi() is True assert descr.bool.impl_is_multi() is True
raises(ValueError, "config.bool = True") raises(ValueError, "config.bool = True")
@ -383,5 +426,6 @@ def test_properties_cached():
c.read_write() c.read_write()
setting = c.cfgimpl_get_settings() setting = c.cfgimpl_get_settings()
option = c.cfgimpl_get_description().sub.b1 option = c.cfgimpl_get_description().sub.b1
option
c._setattr('sub.b1', True, force_permissive=True) c._setattr('sub.b1', True, force_permissive=True)
assert str(setting[b1]) in ["['test']", "[u'test']"] assert str(setting[b1]) in ["['test']", "[u'test']"]

View File

@ -242,6 +242,7 @@ def test_allowed_groups():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1
raises(ValueError, "interface1.impl_set_group_type('toto')") raises(ValueError, "interface1.impl_set_group_type('toto')")
@ -266,6 +267,7 @@ def test_master_not_valid_name():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
invalid_group = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0]) invalid_group = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0])
invalid_group
raises(ValueError, "invalid_group.impl_set_group_type(groups.master)") raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
@ -274,6 +276,7 @@ def test_sub_group_in_master_group():
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
subgroup = OptionDescription("subgroup", '', []) subgroup = OptionDescription("subgroup", '', [])
invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0]) invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])
invalid_group
raises(ValueError, "invalid_group.impl_set_group_type(groups.master)") raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
@ -281,6 +284,7 @@ def test_group_always_has_multis():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau") netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
group
raises(ValueError, "group.impl_set_group_type(groups.master)") raises(ValueError, "group.impl_set_group_type(groups.master)")

View File

@ -3,6 +3,7 @@ from autopath import do_autopath
do_autopath() do_autopath()
from copy import copy from copy import copy
from tiramisu.setting import groups
from tiramisu import setting from tiramisu import setting
setting.expires_time = 1 setting.expires_time = 1
from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption
@ -52,6 +53,7 @@ def test_requires_with_requires():
def test_requires_invalid(): def test_requires_invalid():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', requires='string')") raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
@ -568,6 +570,7 @@ def test_requires_requirement_append():
def test_requires_different_inverse(): def test_requires_different_inverse():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])")
@ -605,5 +608,25 @@ def test_set_item():
def test_properties_conflict(): def test_properties_conflict():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
def test_master_slave_requires():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
assert cfg.ip_admin_eth0.ip_admin_eth0 == []
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2']
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None
raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")

View File

@ -62,21 +62,21 @@ def test_slots_option_readonly():
p = URLOption('p', '') p = URLOption('p', '')
q = FilenameOption('q', '') q = FilenameOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q]) m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
a._requires = 'a' a._requires = (((a,),),)
b._requires = 'b' b._requires = (((a,),),)
c._requires = 'c' c._requires = (((a,),),)
d._requires = 'd' d._requires = (((a,),),)
e._requires = 'e' e._requires = (((a,),),)
g._requires = 'g' g._requires = (((a,),),)
h._requires = 'h' h._requires = (((a,),),)
i._requires = 'i' i._requires = (((a,),),)
j._requires = 'j' j._requires = (((a,),),)
k._requires = 'k' k._requires = (((a,),),)
l._requires = 'l' l._requires = (((a,),),)
m._requires = 'm' m._requires = (((a,),),)
o._requires = 'o' o._requires = (((a,),),)
p._requires = 'p' p._requires = (((a,),),)
q._requires = 'q' q._requires = (((a,),),)
Config(m) Config(m)
raises(AttributeError, "a._requires = 'a'") raises(AttributeError, "a._requires = 'a'")
raises(AttributeError, "b._requires = 'b'") raises(AttributeError, "b._requires = 'b'")

View File

@ -18,10 +18,10 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
"enables us to carry out a calculation and return an option's value" "enables us to carry out a calculation and return an option's value"
from tiramisu.error import PropertiesOptionError, ConfigError, ContextError, \ from .error import PropertiesOptionError, ConfigError, ContextError, \
SlaveError SlaveError
from tiramisu.i18n import _ from .i18n import _
from tiramisu.setting import undefined from .setting import undefined
# ____________________________________________________________ # ____________________________________________________________
@ -222,9 +222,13 @@ def carry_out_calculation(option, context, callback, callback_params,
else: else:
kwargs[key] = couple[0] kwargs[key] = couple[0]
ret = calculate(callback, args, kwargs) ret = calculate(callback, args, kwargs)
if callback_params != {} and isinstance(ret, list) and index is not undefined: try:
if callback_params != {} and isinstance(ret, list) and \
option.impl_is_master_slaves('slave'):
raise SlaveError(_("callback cannot return a list for a " raise SlaveError(_("callback cannot return a list for a "
"slave option ({0})").format(path)) "slave option ({0})").format(path))
except AttributeError:
pass
return ret return ret

View File

@ -22,15 +22,15 @@
import weakref import weakref
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError from .error import PropertiesOptionError, ConfigError, ConflictError
from tiramisu.option import OptionDescription, Option, SymLinkOption, \ from .option import OptionDescription, Option, SymLinkOption, \
DynSymLinkOption DynSymLinkOption
from tiramisu.option.baseoption import valid_name from .option.baseoption import valid_name
from tiramisu.setting import groups, Settings, default_encoding, undefined from .setting import groups, Settings, default_encoding, undefined
from tiramisu.storage import get_storages, get_storage, set_storage, \ from .storage import get_storages, get_storage, set_storage, \
_impl_getstate_setting, get_storages_validation _impl_getstate_setting, get_storages_validation
from tiramisu.value import Values, Multi from .value import Values, Multi
from tiramisu.i18n import _ from .i18n import _
class SubConfig(object): class SubConfig(object):
@ -242,7 +242,7 @@ class SubConfig(object):
return subpath return subpath
def getattr(self, name, force_permissive=False, validate=True, def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined): _setting_properties=undefined, index=None):
""" """
attribute notation mechanism for accessing the value of an option attribute notation mechanism for accessing the value of an option
:param name: attribute name :param name: attribute name
@ -256,23 +256,25 @@ class SubConfig(object):
name, force_permissive=force_permissive) name, force_permissive=force_permissive)
return homeconfig.getattr(name, force_permissive=force_permissive, return homeconfig.getattr(name, force_permissive=force_permissive,
validate=validate, validate=validate,
_setting_properties=_setting_properties) _setting_properties=_setting_properties,
index=index)
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
option = self.cfgimpl_get_description().__getattr__(name, option = self.cfgimpl_get_description().__getattr__(name,
context=context) context=context)
subpath = self._get_subpath(name) subpath = self._get_subpath(name)
if isinstance(option, DynSymLinkOption): if isinstance(option, DynSymLinkOption):
return self.cfgimpl_get_values()._get_cached_item( return self.cfgimpl_get_values()._get_cached_value(
option, path=subpath, option, path=subpath,
validate=validate, validate=validate,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=_setting_properties) setting_properties=_setting_properties, index=index)
elif isinstance(option, SymLinkOption): # pragma: no dynoptiondescription cover elif isinstance(option, SymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt( path = context.cfgimpl_get_description().impl_get_path_by_opt(
option._impl_getopt()) option._impl_getopt())
return context.getattr(path, validate=validate, return context.getattr(path, validate=validate,
force_permissive=force_permissive, force_permissive=force_permissive,
_setting_properties=_setting_properties) _setting_properties=_setting_properties,
index=index)
elif option.impl_is_optiondescription(): elif option.impl_is_optiondescription():
self.cfgimpl_get_settings().validate_properties( self.cfgimpl_get_settings().validate_properties(
option, True, False, path=subpath, option, True, False, path=subpath,
@ -280,11 +282,12 @@ class SubConfig(object):
setting_properties=_setting_properties) setting_properties=_setting_properties)
return SubConfig(option, self._impl_context, subpath) return SubConfig(option, self._impl_context, subpath)
else: else:
return self.cfgimpl_get_values()._get_cached_item( return self.cfgimpl_get_values()._get_cached_value(
option, path=subpath, option, path=subpath,
validate=validate, validate=validate,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=_setting_properties) setting_properties=_setting_properties,
index=index)
def find(self, bytype=None, byname=None, byvalue=undefined, type_='option', def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
check_properties=True, force_permissive=False): check_properties=True, force_permissive=False):

View File

@ -22,12 +22,12 @@ import re
from types import FunctionType from types import FunctionType
import warnings import warnings
from tiramisu.i18n import _ from ..i18n import _
from tiramisu.setting import log, undefined from ..setting import log, undefined
from tiramisu.autolib import carry_out_calculation from ..autolib import carry_out_calculation
from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError,\ from ..error import ConfigError, ValueWarning, PropertiesOptionError,\
ContextError ContextError
from tiramisu.storage import get_storages_option from ..storage import get_storages_option
StorageBase = get_storages_option('base') StorageBase = get_storages_option('base')
@ -853,10 +853,6 @@ def validate_requires_arg(requires, name):
if not isinstance(option, Option): # pragma: optional cover if not isinstance(option, Option): # pragma: optional cover
raise ValueError(_('malformed requirements ' raise ValueError(_('malformed requirements '
'must be an option in option {0}').format(name)) 'must be an option in option {0}').format(name))
if option.impl_is_multi(): # pragma: optional cover
raise ValueError(_('malformed requirements option {0} '
'must not be a multi for {1}').format(
option.impl_getname(), name))
if expected is not None: if expected is not None:
try: try:
option._validate(expected) option._validate(expected)

View File

@ -19,9 +19,9 @@
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/ # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
from tiramisu.i18n import _ from ..i18n import _
from tiramisu.setting import log, undefined from ..setting import log, undefined
from tiramisu.error import SlaveError, ConfigError from ..error import SlaveError, ConfigError, PropertiesOptionError
from .baseoption import DynSymLinkOption, SymLinkOption, Option from .baseoption import DynSymLinkOption, SymLinkOption, Option
@ -112,50 +112,41 @@ class MasterSlaves(object):
for slave in self.getslaves(opt): for slave in self.getslaves(opt):
if not values.is_default_owner(slave, validate_properties=False, if not values.is_default_owner(slave, validate_properties=False,
validate_meta=False, index=index): validate_meta=False, index=index):
values._get_cached_item(slave, validate=False, values._get_cached_value(slave, validate=False,
validate_properties=False validate_properties=False
).pop(index, force=True) ).pop(index, force=True)
pass pass
def getitem(self, values, opt, path, validate, force_permissive, def getitem(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, slave_path=undefined, force_properties, validate_properties, slave_path=undefined,
slave_value=undefined, setting_properties=undefined, self_properties=undefined): slave_value=undefined, setting_properties=undefined,
self_properties=undefined, index=None):
if self.is_master(opt): if self.is_master(opt):
return self._getmaster(values, opt, path, validate, return self._getmaster(values, opt, path, validate,
force_permissive, force_properties, force_permissive, force_properties,
validate_properties, slave_path, validate_properties, slave_path,
slave_value, self_properties) slave_value, self_properties, index)
else: else:
return self._getslave(values, opt, path, validate, return self._getslave(values, opt, path, validate,
force_permissive, force_properties, force_permissive, force_properties,
validate_properties, setting_properties, self_properties) validate_properties, setting_properties,
self_properties, index)
def _getmaster(self, values, opt, path, validate, force_permissive, def _getmaster(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, c_slave_path, force_properties, validate_properties, c_slave_path,
c_slave_value, self_properties): c_slave_value, self_properties, index):
value = values._get_validated_value(opt, path, validate, value = values._get_validated_value(opt, path, validate,
force_permissive, force_permissive,
force_properties, force_properties,
validate_properties, validate_properties,
self_properties=self_properties) self_properties=self_properties,
if validate is True: index=index)
if index is None and validate is True:
masterlen = len(value) masterlen = len(value)
for slave in self.getslaves(opt): for slave in self.getslaves(opt):
try: try:
slave_path = slave.impl_getpath(values._getcontext()) slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path) slavelen = values._p_.get_max_length(slave_path)
#if c_slave_path == slave_path:
# slave_value = c_slave_value
#else:
# slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# self_properties=self_properties,
# masterlen=masterlen)
#slavelen = len(slave_value)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt) self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
except ConfigError: # pragma: optional cover except ConfigError: # pragma: optional cover
pass pass
@ -163,7 +154,7 @@ class MasterSlaves(object):
def _getslave(self, values, opt, path, validate, force_permissive, def _getslave(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, setting_properties, force_properties, validate_properties, setting_properties,
self_properties): self_properties, index):
""" """
if master has length 0: if master has length 0:
return [] return []
@ -191,46 +182,43 @@ class MasterSlaves(object):
masterlen = self.get_length(values, opt, validate, undefined, masterlen = self.get_length(values, opt, validate, undefined,
undefined, force_permissive, undefined, force_permissive,
master=master) master=master)
master_is_meta = values._is_meta(opt, masterp) master_is_meta = values._is_meta(master, masterp)
#value = values._get_validated_value(opt, path, validate, multi = values._get_multi(opt, path)
# force_permissive, if masterlen == 0:
# force_properties,
# validate_properties,
# None, # not undefined
# with_meta=master_is_meta,
# self_properties=self_properties)
#if slave, had values until master's one
#path = opt.impl_getpath(context)
#valuelen = len(value)
#if validate:
# self.validate_slave_length(masterlen, valuelen,
# opt.impl_getname(), opt)
#if valuelen < masterlen:
#FIXME voir si pas de plus grande valeur !
value = values._get_multi(opt, path)
for index in range(0, masterlen):
#index = valuelen + num
value.append(values._get_validated_value(opt, path, validate,
force_permissive, force_properties,
validate_properties,
with_meta=master_is_meta,
index=index,
self_properties=self_properties,
masterlen=masterlen),
setitem=False,
force=True,
validate=validate)
#FIXME hu?
if validate_properties: if validate_properties:
context.cfgimpl_get_settings().validate_properties(opt, False, context.cfgimpl_get_settings().validate_properties(opt, False,
False, False,
value=value, value=multi,
path=path, path=path,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties, force_properties=force_properties,
setting_properties=setting_properties) setting_properties=setting_properties)
return value else:
one_has_value = False
if index is None:
indexes = range(0, masterlen)
else:
indexes = [index]
for idx in indexes:
try:
value = values._get_cached_value(opt, path, validate,
force_permissive, force_properties,
validate_properties,
with_meta=master_is_meta,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
masterlen=masterlen,
from_masterslave=True)
multi.append(value, setitem=False, force=True, validate=validate)
one_has_value = True
except PropertiesOptionError, err:
multi.append_properties_error(err)
if not one_has_value:
#raise last err
raise err
return multi
def setitem(self, values, opt, value, path): def setitem(self, values, opt, value, path):
if self.is_master(opt): if self.is_master(opt):
@ -241,15 +229,6 @@ class MasterSlaves(object):
slave_path = base_path + slave.impl_getname() slave_path = base_path + slave.impl_getname()
slavelen = values._p_.get_max_length(slave_path) slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt) self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
#slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# masterlen=masterlen) # not undefined
#slavelen = len(slave_value)
#self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
else: else:
self.validate_slave_length(self.get_length(values, opt, self.validate_slave_length(self.get_length(values, opt,
slave_path=path), len(value), slave_path=path), len(value),

View File

@ -23,12 +23,12 @@ import re
import sys import sys
from IPy import IP from IPy import IP
from types import FunctionType from types import FunctionType
from tiramisu.setting import log, undefined from ..setting import log, undefined
from tiramisu.error import ConfigError, ContextError from ..error import ConfigError, ContextError
from tiramisu.i18n import _ from ..i18n import _
from .baseoption import Option, validate_callback from .baseoption import Option, validate_callback
from tiramisu.autolib import carry_out_calculation from ..autolib import carry_out_calculation
class ChoiceOption(Option): class ChoiceOption(Option):

View File

@ -22,13 +22,13 @@ from copy import copy
import re import re
from tiramisu.i18n import _ from ..i18n import _
from tiramisu.setting import groups, undefined # , log from ..setting import groups, undefined # , log
from .baseoption import BaseOption, SymLinkOption, allowed_character from .baseoption import BaseOption, SymLinkOption, allowed_character
from . import MasterSlaves from . import MasterSlaves
from tiramisu.error import ConfigError, ConflictError from ..error import ConfigError, ConflictError
from tiramisu.storage import get_storages_option from ..storage import get_storages_option
from tiramisu.autolib import carry_out_calculation from ..autolib import carry_out_calculation
StorageOptionDescription = get_storages_option('optiondescription') StorageOptionDescription = get_storages_option('optiondescription')
@ -135,6 +135,19 @@ class OptionDescription(BaseOption, StorageOptionDescription):
option._set_readonly() option._set_readonly()
if isinstance(option, OptionDescription): if isinstance(option, OptionDescription):
option.impl_validate_options(cache_option) option.impl_validate_options(cache_option)
if option.impl_getrequires() != []:
for requires in option.impl_getrequires():
for require in requires:
if require[0].impl_is_multi():
if option.impl_is_master_slaves('slave') and require[0].impl_is_master_slaves():
if option.impl_get_master_slaves() != require[0].impl_get_master_slaves():
raise ValueError(_('malformed requirements option {0} '
'must be in same master/slaves for {1}').format(
require[0].impl_getname(), option.impl_getname()))
else:
raise ValueError(_('malformed requirements option {0} '
'must not be a multi for {1}').format(
require[0].impl_getname(), option.impl_getname()))
if init: if init:
if len(cache_option) != len(set(cache_option)): if len(cache_option) != len(set(cache_option)):
for idx in xrange(1, len(cache_option) + 1): for idx in xrange(1, len(cache_option) + 1):

View File

@ -19,9 +19,9 @@ from time import time
from copy import copy from copy import copy
from logging import getLogger from logging import getLogger
import weakref import weakref
from tiramisu.error import (RequirementError, PropertiesOptionError, from .error import (RequirementError, PropertiesOptionError,
ConstError, ConfigError) ConstError, ConfigError)
from tiramisu.i18n import _ from .i18n import _
"Default encoding for display a Config if raise UnicodeEncodeError" "Default encoding for display a Config if raise UnicodeEncodeError"
@ -367,7 +367,7 @@ class Settings(object):
def _getproperties(self, opt=None, path=None, def _getproperties(self, opt=None, path=None,
setting_properties=undefined, read_write=True, setting_properties=undefined, read_write=True,
apply_requires=True): apply_requires=True, index=None):
""" """
""" """
if opt is None: if opt is None:
@ -384,17 +384,17 @@ class Settings(object):
ntime = int(time()) ntime = int(time())
else: else:
ntime = None ntime = None
if 'cache' in setting_properties and self._p_.hascache(path): if 'cache' in setting_properties and self._p_.hascache(path, index):
is_cached, props = self._p_.getcache(path, ntime) is_cached, props = self._p_.getcache(path, ntime, index)
if not is_cached: if not is_cached:
props = self._p_.getproperties(path, opt.impl_getproperties()) props = self._p_.getproperties(path, opt.impl_getproperties())
if apply_requires: if apply_requires:
props = copy(props) props = copy(props)
props |= self.apply_requires(opt, path, setting_properties) props |= self.apply_requires(opt, path, setting_properties, index)
if 'cache' in setting_properties: if 'cache' in setting_properties:
if 'expire' in setting_properties: if 'expire' in setting_properties:
ntime = ntime + expires_time ntime = ntime + expires_time
self._p_.setcache(path, props, ntime) self._p_.setcache(path, props, ntime, index)
if read_write: if read_write:
props = copy(props) props = copy(props)
return props return props
@ -458,7 +458,8 @@ class Settings(object):
properties = copy(self_properties) properties = copy(self_properties)
else: else:
properties = self._getproperties(opt_or_descr, path, properties = self._getproperties(opt_or_descr, path,
setting_properties=setting_properties) setting_properties=setting_properties,
index=index)
# remove opt permissive # remove opt permissive
# permissive affect option's permission with or without permissive # permissive affect option's permission with or without permissive
# global property # global property
@ -571,7 +572,7 @@ class Settings(object):
else: else:
self._p_.reset_all_cache() self._p_.reset_all_cache()
def apply_requires(self, opt, path, setting_properties): def apply_requires(self, opt, path, setting_properties, index):
"""carries out the jit (just in time) requirements between options """carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's a requirement is a tuple of this form that comes from the option's
@ -633,7 +634,8 @@ class Settings(object):
"'{1}'").format(path, reqpath)) "'{1}'").format(path, reqpath))
try: try:
value = context.getattr(reqpath, force_permissive=True, value = context.getattr(reqpath, force_permissive=True,
_setting_properties=setting_properties) _setting_properties=setting_properties,
index=index)
except PropertiesOptionError as err: except PropertiesOptionError as err:
if not transitive: if not transitive:
continue continue

View File

@ -29,8 +29,11 @@ configurator ``set_storage()``.
from time import time from time import time
from random import randint from random import randint
import os import os
from tiramisu.error import ConfigError from ..error import ConfigError
from tiramisu.i18n import _ from ..i18n import _
MODULE_PATH = os.path.split(os.path.split(os.path.split(__file__)[0])[0])[1]
class StorageType(object): class StorageType(object):
@ -53,7 +56,7 @@ class StorageType(object):
if self.storage_type is None: if self.storage_type is None:
self.storage_type = self.default_storage self.storage_type = self.default_storage
if self.mod is None: if self.mod is None:
modulepath = 'tiramisu.storage.{0}'.format(self.storage_type) modulepath = '{0}.storage.{1}'.format(MODULE_PATH, self.storage_type)
try: try:
mod = __import__(modulepath) mod = __import__(modulepath)
except ImportError: except ImportError:

View File

@ -17,9 +17,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# #
# ____________________________________________________________ # ____________________________________________________________
from tiramisu.i18n import _ from ...i18n import _
from tiramisu.setting import undefined from ...setting import undefined
from tiramisu.error import ConfigError from ...error import ConfigError
#____________________________________________________________ #____________________________________________________________

View File

@ -14,8 +14,8 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from tiramisu.i18n import _ from ...i18n import _
from tiramisu.error import ConfigError from ...error import ConfigError
from ..util import SerializeObject from ..util import SerializeObject

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from ..util import Cache from ..util import Cache
from tiramisu.setting import undefined from ...setting import undefined
class Values(Cache): class Values(Cache):

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from tiramisu.setting import owners from ..setting import owners
class SerializeObject(object): class SerializeObject(object):
@ -97,26 +97,29 @@ class Cache(object):
value = tuple(_value) value = tuple(_value)
setattr(self, key, value) setattr(self, key, value)
def setcache(self, path, val, time): def setcache(self, path, val, time, index):
self._cache[path] = (val, time) self._cache.setdefault(path, {})[index] = (val, time)
def getcache(self, path, exp): def getcache(self, path, exp, index):
value, created = self._cache[path] value, created = self._cache[path][index]
if created is None or exp <= created: if created is None or exp <= created:
return True, value return True, value
return False, None return False, None
def hascache(self, path): def hascache(self, path, index):
""" path is in the cache """ path is in the cache
:param path: the path's option :param path: the path's option
""" """
return path in self._cache return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp): def reset_expired_cache(self, exp):
for key in tuple(self._cache.keys()): for key in self._cache.keys():
val, created = self._cache[key] for index in self._cache[key].keys():
val, created = self._cache[key][index]
if created is not None and exp > created: if created is not None and exp > created:
del(self._cache[key][index])
if self._cache[key] == {}:
del(self._cache[key]) del(self._cache[key])
def reset_all_cache(self): def reset_all_cache(self):
@ -125,6 +128,6 @@ class Cache(object):
def get_cached(self, context): def get_cached(self, context):
"""return all values in a dictionary """return all values in a dictionary
example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')} example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
""" """
return self._cache return self._cache

View File

@ -18,11 +18,11 @@
from time import time from time import time
import sys import sys
import weakref import weakref
from tiramisu.error import ConfigError, SlaveError, PropertiesOptionError from .error import ConfigError, SlaveError, PropertiesOptionError
from tiramisu.setting import owners, expires_time, undefined from .setting import owners, expires_time, undefined
from tiramisu.autolib import carry_out_calculation from .autolib import carry_out_calculation
from tiramisu.i18n import _ from .i18n import _
from tiramisu.option import SymLinkOption, DynSymLinkOption, Option from .option import SymLinkOption, DynSymLinkOption, Option
class Values(object): class Values(object):
@ -65,7 +65,7 @@ class Values(object):
callback=callback, callback=callback,
callback_params=callback_params, callback_params=callback_params,
index=index) index=index)
if isinstance(value, list) and index is not undefined: if isinstance(value, list) and index is not None:
#if return a list and index is set, return value only if #if return a list and index is set, return value only if
#it's a submulti without submulti_index and without list of list #it's a submulti without submulti_index and without list of list
if opt.impl_is_submulti() and submulti_index is undefined and \ if opt.impl_is_submulti() and submulti_index is undefined and \
@ -78,9 +78,9 @@ class Values(object):
if meta is not None: if meta is not None:
try: try:
value = meta.cfgimpl_get_values( value = meta.cfgimpl_get_values(
)._get_cached_item(opt, path) )._get_cached_value(opt, path, index=index, from_masterslave=True)
if isinstance(value, Multi): if isinstance(value, Multi):
if index is not undefined: if index is not None:
value = value[index] value = value[index]
else: else:
value = list(value) value = list(value)
@ -89,7 +89,7 @@ class Values(object):
pass pass
# now try to get default value # now try to get default value
value = opt.impl_getdefault() value = opt.impl_getdefault()
if opt.impl_is_multi() and index is not undefined: if opt.impl_is_multi() and index is not None:
if value == []: if value == []:
value = opt.impl_getdefault_multi() value = opt.impl_getdefault_multi()
else: else:
@ -115,7 +115,7 @@ class Values(object):
return self._p_.getvalue(path, index) return self._p_.getvalue(path, index)
else: else:
value = self._p_.getvalue(path) value = self._p_.getvalue(path)
if index is not undefined: if index is not None:
try: try:
return value[index] return value[index]
except IndexError: except IndexError:
@ -204,13 +204,15 @@ class Values(object):
def getitem(self, opt, validate=True, force_permissive=False): def getitem(self, opt, validate=True, force_permissive=False):
""" """
""" """
return self._get_cached_item(opt, validate=validate, return self._get_cached_value(opt, validate=validate,
force_permissive=force_permissive) force_permissive=force_permissive)
def _get_cached_item(self, opt, path=None, validate=True, def _get_cached_value(self, opt, path=None, validate=True,
force_permissive=False, force_properties=None, force_permissive=False, force_properties=None,
validate_properties=True, validate_properties=True,
setting_properties=undefined, self_properties=undefined): setting_properties=undefined, self_properties=undefined,
index=None, from_masterslave=False, with_meta=True,
masterlen=undefined):
untrusted_cached_properties = force_properties is None untrusted_cached_properties = force_properties is None
context = self._getcontext() context = self._getcontext()
if path is None: if path is None:
@ -221,13 +223,14 @@ class Values(object):
)._getproperties(read_write=False) )._getproperties(read_write=False)
if self_properties is undefined: if self_properties is undefined:
self_properties = context.cfgimpl_get_settings()._getproperties( self_properties = context.cfgimpl_get_settings()._getproperties(
opt, path, read_write=False, setting_properties=setting_properties) opt, path, read_write=False,
if 'cache' in setting_properties and self._p_.hascache(path): setting_properties=setting_properties, index=index)
if 'cache' in setting_properties and self._p_.hascache(path, index):
if 'expire' in setting_properties: if 'expire' in setting_properties:
ntime = int(time()) ntime = int(time())
is_cached, value = self._p_.getcache(path, ntime) is_cached, value = self._p_.getcache(path, ntime, index)
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) and index is None:
value = Multi(value, self.context, opt, path) value = Multi(value, self.context, opt, path)
if not untrusted_cached_properties: if not untrusted_cached_properties:
# revalidate properties (because not default properties) # revalidate properties (because not default properties)
@ -236,42 +239,41 @@ class Values(object):
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties, force_properties=force_properties,
setting_properties=setting_properties, setting_properties=setting_properties,
self_properties=self_properties) self_properties=self_properties,
index=index)
return value return value
val = self._getitem(opt, path, validate, force_permissive, if not from_masterslave and opt.impl_is_master_slaves():
force_properties, validate_properties, val = opt.impl_get_master_slaves().getitem(self, opt, path,
setting_properties, self_properties=self_properties)
if 'cache' in setting_properties and validate and validate_properties \
and force_permissive is False and force_properties is None:
if 'expire' in setting_properties:
if ntime is None:
ntime = int(time())
ntime = ntime + expires_time
self._p_.setcache(path, val, ntime)
return val
def _getitem(self, opt, path, validate, force_permissive, force_properties,
validate_properties, setting_properties=undefined,
self_properties=undefined):
if opt.impl_is_master_slaves():
return opt.impl_get_master_slaves().getitem(self, opt, path,
validate, validate,
force_permissive, force_permissive,
force_properties, force_properties,
validate_properties, validate_properties,
setting_properties=setting_properties, setting_properties=setting_properties,
index=index,
self_properties=self_properties) self_properties=self_properties)
else: else:
return self._get_validated_value(opt, path, validate, val = self._get_validated_value(opt, path, validate,
force_permissive, force_permissive,
force_properties, force_properties,
validate_properties, validate_properties,
setting_properties=setting_properties, setting_properties=setting_properties,
self_properties=self_properties) self_properties=self_properties,
with_meta=with_meta,
masterlen=masterlen,
index=index)
# cache doesn't work with SubMulti yet
if not isinstance(val, SubMulti) and 'cache' in setting_properties and validate and validate_properties \
and force_permissive is False and force_properties is None:
if 'expire' in setting_properties:
if ntime is None:
ntime = int(time())
ntime = ntime + expires_time
self._p_.setcache(path, val, ntime, index)
return val
def _get_validated_value(self, opt, path, validate, force_permissive, def _get_validated_value(self, opt, path, validate, force_permissive,
force_properties, validate_properties, force_properties, validate_properties,
index=undefined, submulti_index=undefined, index=None, submulti_index=undefined,
with_meta=True, setting_properties=undefined, with_meta=True, setting_properties=undefined,
self_properties=undefined, masterlen=undefined): self_properties=undefined, masterlen=undefined):
"""same has getitem but don't touch the cache """same has getitem but don't touch the cache
@ -282,7 +284,7 @@ class Values(object):
if setting_properties is undefined: if setting_properties is undefined:
setting_properties = setting._getproperties(read_write=False) setting_properties = setting._getproperties(read_write=False)
if self_properties is undefined: if self_properties is undefined:
self_properties = setting._getproperties(opt, path, read_write=False) self_properties = setting._getproperties(opt, path, read_write=False, index=index)
is_default = self._is_default_owner(opt, path, is_default = self._is_default_owner(opt, path,
validate_properties=False, validate_properties=False,
validate_meta=False, validate_meta=False,
@ -458,7 +460,7 @@ class Values(object):
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties: if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default return owners.default
if validate_properties: if validate_properties:
self._getitem(opt, path, True, force_permissive, None, True, self._get_cached_value(opt, path, True, force_permissive, None, True,
self_properties=self_properties) self_properties=self_properties)
owner = self._p_.getowner(path, owners.default, only_default=only_default, index=index) owner = self._p_.getowner(path, owners.default, only_default=only_default, index=index)
if validate_meta is undefined: if validate_meta is undefined:
@ -601,7 +603,7 @@ class Values(object):
setting_properties=setting_properties) setting_properties=setting_properties)
if 'mandatory' in self_properties: if 'mandatory' in self_properties:
try: try:
self._get_cached_item(true_opt, path=true_path, self._get_cached_value(true_opt, path=true_path,
force_properties=frozenset(('mandatory',)), force_properties=frozenset(('mandatory',)),
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties,
@ -710,7 +712,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False) setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate: if 'validator' in setting_properties and validate:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item( fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False) self.opt, path=self.path, validate=False)
fake_multi._setitem(index, value, validate=False) fake_multi._setitem(index, value, validate=False)
self._validate(value, fake_context, index, True) self._validate(value, fake_context, index, True)
@ -721,8 +723,11 @@ class Multi(list):
#def __repr__(self, *args, **kwargs): #def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs) # return super(Multi, self).__repr__(*args, **kwargs)
#def __getitem__(self, y): def __getitem__(self, index):
# return super(Multi, self).__getitem__(y) value = super(Multi, self).__getitem__(index)
if isinstance(value, PropertiesOptionError):
raise value
return value
def _get_validated_value(self, index): def _get_validated_value(self, index):
values = self._getcontext().cfgimpl_get_values() values = self._getcontext().cfgimpl_get_values()
@ -740,12 +745,13 @@ class Multi(list):
index = self.__len__() index = self.__len__()
if value is undefined: if value is undefined:
value = self._get_validated_value(index) value = self._get_validated_value(index)
if validate and value not in [None, undefined]:
context = self._getcontext() context = self._getcontext()
setting = context.cfgimpl_get_settings() setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False) setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value not in [None, undefined]: if 'validator' in setting_properties:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item( fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False) self.opt, path=self.path, validate=False)
fake_multi.append(value, validate=False, force=True) fake_multi.append(value, validate=False, force=True)
self._validate(value, fake_context, index, True) self._validate(value, fake_context, index, True)
@ -757,6 +763,9 @@ class Multi(list):
if setitem: if setitem:
self._store(force=force) self._store(force=force)
def append_properties_error(self, err):
super(Multi, self).append(err)
def sort(self, cmp=None, key=None, reverse=False): def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_is_master_slaves(): if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot sort multi option {0} if master or slave" raise SlaveError(_("cannot sort multi option {0} if master or slave"
@ -786,7 +795,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False) setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value is not None: if 'validator' in setting_properties and validate and value is not None:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item( fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False) self.opt, path=self.path, validate=False)
fake_multi.insert(index, value, validate=False) fake_multi.insert(index, value, validate=False)
self._validate(value, fake_context, index, True) self._validate(value, fake_context, index, True)
@ -806,7 +815,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False) setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate: if 'validator' in setting_properties and validate:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item( fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False) self.opt, path=self.path, validate=False)
fake_multi.extend(iterable, validate=False) fake_multi.extend(iterable, validate=False)
self._validate(iterable, fake_context, index) self._validate(iterable, fake_context, index)