optimise mandatory_warnings
This commit is contained in:
parent
64e9171ea6
commit
a0de1109f7
7 changed files with 307 additions and 135 deletions
|
@ -6,7 +6,7 @@ from tiramisu import setting
|
|||
setting.expires_time = 1
|
||||
from tiramisu.option import IntOption, OptionDescription
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.error import ConfigError
|
||||
from tiramisu.error import ConfigError, PropertiesOptionError
|
||||
|
||||
|
||||
from time import sleep, time
|
||||
|
|
|
@ -284,7 +284,7 @@ def test_mandatory_dyndescription():
|
|||
del(cfg.od.dodval1.stval1)
|
||||
cfg.read_only()
|
||||
raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
|
||||
assert cfg.cfgimpl_get_values().mandatory_warnings() == ['od.dodval1.stval1', 'od.dodval2.stval2']
|
||||
assert list(cfg.cfgimpl_get_values().mandatory_warnings()) == ['od.dodval1.stval1', 'od.dodval2.stval2']
|
||||
|
||||
|
||||
def test_build_dyndescription_context():
|
||||
|
@ -467,7 +467,7 @@ def test_mandatory_dyndescription_context():
|
|||
del(cfg.od.dodval1.stval1)
|
||||
cfg.read_only()
|
||||
raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
|
||||
assert cfg.cfgimpl_get_values().mandatory_warnings() == ['od.dodval1.stval1', 'od.dodval2.stval2']
|
||||
assert list(cfg.cfgimpl_get_values().mandatory_warnings()) == ['od.dodval1.stval1', 'od.dodval2.stval2']
|
||||
|
||||
|
||||
def test_increase_dyndescription_context():
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
# coding: utf-8
|
||||
from autopath import do_autopath
|
||||
do_autopath()
|
||||
from time import sleep
|
||||
|
||||
from py.test import raises
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import StrOption, UnicodeOption, OptionDescription
|
||||
from tiramisu.error import PropertiesOptionError
|
||||
from tiramisu.option import IntOption, StrOption, UnicodeOption, OptionDescription, SymLinkOption
|
||||
from tiramisu.error import PropertiesOptionError, ConfigError
|
||||
from tiramisu.setting import groups
|
||||
|
||||
|
||||
|
@ -25,6 +24,61 @@ def make_description():
|
|||
return descr
|
||||
|
||||
|
||||
def return_value(value):
|
||||
return value
|
||||
|
||||
|
||||
def make_description2():
|
||||
stroption = StrOption('str', 'Test string option', default="abc",
|
||||
properties=('mandatory', ))
|
||||
stroption1 = StrOption('str1', 'Test string option',
|
||||
properties=('mandatory', ))
|
||||
stroption2 = SymLinkOption('unicode2', stroption1)
|
||||
stroption3 = StrOption('str3', 'Test string option', multi=True,
|
||||
properties=('mandatory', ))
|
||||
unicode1 = UnicodeOption('unicode1', 'Test string option', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', ))
|
||||
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1])
|
||||
return descr
|
||||
|
||||
|
||||
def make_description_sym():
|
||||
stroption = StrOption('str', 'Test string option', default="abc",
|
||||
properties=('mandatory', ))
|
||||
stroption1 = StrOption('str1', 'Test string option',
|
||||
properties=('mandatory', ))
|
||||
stroption2 = SymLinkOption('unicode2', stroption1)
|
||||
stroption3 = StrOption('str3', 'Test string option', multi=True,
|
||||
properties=('mandatory', ))
|
||||
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
|
||||
return descr
|
||||
|
||||
|
||||
def make_description3():
|
||||
stroption = StrOption('str', 'Test string option', default="abc",
|
||||
properties=('mandatory', ))
|
||||
stroption1 = StrOption('str1', 'Test string option',
|
||||
properties=('mandatory', ))
|
||||
stroption2 = SymLinkOption('unicode2', stroption1)
|
||||
stroption3 = StrOption('str3', 'Test string option', multi=True,
|
||||
properties=('mandatory', ))
|
||||
unicode1 = UnicodeOption('unicode1', 'Test string option', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', ))
|
||||
int1 = IntOption('int1', '', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', ))
|
||||
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1, int1])
|
||||
return descr
|
||||
|
||||
|
||||
def make_description4():
|
||||
stroption = StrOption('str', 'Test string option', default="abc",
|
||||
properties=('mandatory', ))
|
||||
stroption1 = StrOption('str1', 'Test string option',
|
||||
properties=('mandatory', ))
|
||||
stroption2 = UnicodeOption('unicode2', 'Test string option',
|
||||
properties=('mandatory', ))
|
||||
stroption3 = StrOption('str3', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}])
|
||||
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
|
||||
return descr
|
||||
|
||||
|
||||
def test_mandatory_ro():
|
||||
descr = make_description()
|
||||
config = Config(descr)
|
||||
|
@ -255,13 +309,12 @@ def test_mandatory_warnings_ro():
|
|||
except PropertiesOptionError as err:
|
||||
proc = err.proptype
|
||||
assert proc == ['mandatory']
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
config.read_write()
|
||||
config.str = 'a'
|
||||
config.read_only()
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
|
||||
sleep(.1)
|
||||
|
||||
|
||||
def test_mandatory_warnings_rw():
|
||||
|
@ -270,11 +323,10 @@ def test_mandatory_warnings_rw():
|
|||
config.str = ''
|
||||
config.read_write()
|
||||
config.str
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
config.str = 'a'
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
|
||||
sleep(.1)
|
||||
|
||||
|
||||
def test_mandatory_warnings_disabled():
|
||||
|
@ -284,11 +336,10 @@ def test_mandatory_warnings_disabled():
|
|||
setting = config.cfgimpl_get_settings()
|
||||
config.read_write()
|
||||
config.str
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
setting[descr.str].append('disabled')
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
|
||||
sleep(.1)
|
||||
|
||||
|
||||
def test_mandatory_warnings_hidden():
|
||||
|
@ -312,11 +363,10 @@ def test_mandatory_warnings_frozen():
|
|||
setting = config.cfgimpl_get_settings()
|
||||
config.read_write()
|
||||
config.str
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
setting[descr.str].append('frozen')
|
||||
config.read_only()
|
||||
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
|
||||
sleep(.1)
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_master():
|
||||
|
@ -401,3 +451,60 @@ def test_mandatory_slave():
|
|||
config.read_only()
|
||||
assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
|
||||
assert config.ip_admin_eth0.netmask_admin_eth0 == ['ip']
|
||||
|
||||
|
||||
def test_mandatory_warnings_symlink():
|
||||
descr = make_description_sym()
|
||||
config = Config(descr)
|
||||
config.str = ''
|
||||
setting = config.cfgimpl_get_settings()
|
||||
config.read_write()
|
||||
config.str
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
setting[descr.str].append('frozen')
|
||||
config.read_only()
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_warnings_validate():
|
||||
descr = make_description3()
|
||||
config = Config(descr)
|
||||
config.str = ''
|
||||
raises(ValueError, "list(config.cfgimpl_get_values().mandatory_warnings())")
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str', 'str1', 'unicode2', 'str3', 'unicode1', 'int1']
|
||||
config.str = 'test'
|
||||
raises(ValueError, "list(config.cfgimpl_get_values().mandatory_warnings())")
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_warnings_validate_empty():
|
||||
descr = make_description2()
|
||||
config = Config(descr)
|
||||
config.str = ''
|
||||
config.read_only()
|
||||
raises(ConfigError, "list(config.cfgimpl_get_values().mandatory_warnings())")
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str', 'str1', 'unicode2', 'str3', 'unicode1']
|
||||
|
||||
|
||||
def test_mandatory_warnings_requires():
|
||||
descr = make_description4()
|
||||
config = Config(descr)
|
||||
config.str = ''
|
||||
config.read_write()
|
||||
config.str
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2']
|
||||
config.read_only()
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2']
|
||||
config.read_write()
|
||||
config.str = 'yes'
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_od_disabled():
|
||||
descr = make_description()
|
||||
od = OptionDescription('od', '', [descr])
|
||||
config = Config(od)
|
||||
config.read_only()
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['tiram.str1', 'tiram.unicode2', 'tiram.str3']
|
||||
config.cfgimpl_get_settings()[descr].append('disabled')
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == []
|
||||
|
|
|
@ -241,7 +241,8 @@ class SubConfig(object):
|
|||
subpath = self._impl_path + '.' + name
|
||||
return subpath
|
||||
|
||||
def getattr(self, name, force_permissive=False, validate=True):
|
||||
def getattr(self, name, force_permissive=False, validate=True,
|
||||
_setting_properties=undefined):
|
||||
"""
|
||||
attribute notation mechanism for accessing the value of an option
|
||||
:param name: attribute name
|
||||
|
@ -254,7 +255,8 @@ class SubConfig(object):
|
|||
homeconfig, name = self.cfgimpl_get_home_by_path(
|
||||
name, force_permissive=force_permissive)
|
||||
return homeconfig.getattr(name, force_permissive=force_permissive,
|
||||
validate=validate)
|
||||
validate=validate,
|
||||
_setting_properties=_setting_properties)
|
||||
context = self._cfgimpl_get_context()
|
||||
option = self.cfgimpl_get_description().__getattr__(name,
|
||||
context=context)
|
||||
|
@ -263,22 +265,26 @@ class SubConfig(object):
|
|||
return self.cfgimpl_get_values()._get_cached_item(
|
||||
option, path=subpath,
|
||||
validate=validate,
|
||||
force_permissive=force_permissive)
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=_setting_properties)
|
||||
elif isinstance(option, SymLinkOption): # pragma: no dynoptiondescription cover
|
||||
path = context.cfgimpl_get_description().impl_get_path_by_opt(
|
||||
option._impl_getopt())
|
||||
return context.getattr(path, validate=validate,
|
||||
force_permissive=force_permissive)
|
||||
force_permissive=force_permissive,
|
||||
_setting_properties=_setting_properties)
|
||||
elif option.impl_is_optiondescription():
|
||||
self.cfgimpl_get_settings().validate_properties(
|
||||
option, True, False, path=subpath,
|
||||
force_permissive=force_permissive)
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=_setting_properties)
|
||||
return SubConfig(option, self._impl_context, subpath)
|
||||
else:
|
||||
return self.cfgimpl_get_values()._get_cached_item(
|
||||
option, path=subpath,
|
||||
validate=validate,
|
||||
force_permissive=force_permissive)
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=_setting_properties)
|
||||
|
||||
def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
|
||||
check_properties=True, force_permissive=False):
|
||||
|
|
|
@ -115,25 +115,25 @@ class MasterSlaves(object):
|
|||
|
||||
def getitem(self, values, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties, slave_path=undefined,
|
||||
slave_value=undefined, setting_properties=undefined, settings=undefined):
|
||||
slave_value=undefined, setting_properties=undefined, self_properties=undefined):
|
||||
if self.is_master(opt):
|
||||
return self._getmaster(values, opt, path, validate,
|
||||
force_permissive, force_properties,
|
||||
validate_properties, slave_path,
|
||||
slave_value, settings)
|
||||
slave_value, self_properties)
|
||||
else:
|
||||
return self._getslave(values, opt, path, validate,
|
||||
force_permissive, force_properties,
|
||||
validate_properties, setting_properties, settings)
|
||||
validate_properties, setting_properties, self_properties)
|
||||
|
||||
def _getmaster(self, values, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties, c_slave_path,
|
||||
c_slave_value, settings):
|
||||
c_slave_value, self_properties):
|
||||
value = values._get_validated_value(opt, path, validate,
|
||||
force_permissive,
|
||||
force_properties,
|
||||
validate_properties,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
if validate is True:
|
||||
masterlen = len(value)
|
||||
for slave in self.getslaves(opt):
|
||||
|
@ -148,7 +148,7 @@ class MasterSlaves(object):
|
|||
False,
|
||||
None, False,
|
||||
None,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
slavelen = len(slave_value)
|
||||
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
|
||||
except ConfigError: # pragma: optional cover
|
||||
|
@ -157,7 +157,7 @@ class MasterSlaves(object):
|
|||
|
||||
def _getslave(self, values, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties, setting_properties,
|
||||
settings):
|
||||
self_properties):
|
||||
"""
|
||||
if master has length 0:
|
||||
return []
|
||||
|
@ -192,7 +192,7 @@ class MasterSlaves(object):
|
|||
validate_properties,
|
||||
None, # not undefined
|
||||
with_meta=master_is_meta,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
#if slave, had values until master's one
|
||||
path = opt.impl_getpath(context)
|
||||
valuelen = len(value)
|
||||
|
@ -207,7 +207,7 @@ class MasterSlaves(object):
|
|||
validate_properties=False,
|
||||
with_meta=master_is_meta,
|
||||
index=index,
|
||||
settings=settings),
|
||||
self_properties=self_properties),
|
||||
setitem=False,
|
||||
force=True,
|
||||
validate=validate)
|
||||
|
@ -218,7 +218,7 @@ class MasterSlaves(object):
|
|||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties,
|
||||
self_properties=setting_properties)
|
||||
setting_properties=setting_properties)
|
||||
return value
|
||||
|
||||
def setitem(self, values, opt, value, path):
|
||||
|
|
|
@ -330,19 +330,19 @@ class Settings(object):
|
|||
# properties methods
|
||||
def __contains__(self, propname):
|
||||
"enables the pythonic 'in' syntaxic sugar"
|
||||
return propname in self._getproperties()
|
||||
return propname in self._getproperties(read_write=False)
|
||||
|
||||
def __repr__(self):
|
||||
return str(list(self._getproperties()))
|
||||
return str(list(self._getproperties(read_write=False)))
|
||||
|
||||
def __getitem__(self, opt):
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self._getitem(opt, path)
|
||||
|
||||
def _getitem(self, opt, path, self_properties=undefined):
|
||||
def _getitem(self, opt, path, setting_properties=undefined):
|
||||
return Property(self,
|
||||
self._getproperties(opt, path,
|
||||
self_properties=self_properties),
|
||||
setting_properties=setting_properties),
|
||||
opt, path)
|
||||
|
||||
def __setitem__(self, opt, value): # pragma: optional cover
|
||||
|
@ -361,41 +361,45 @@ class Settings(object):
|
|||
self._getcontext().cfgimpl_reset_cache()
|
||||
|
||||
def _getproperties(self, opt=None, path=None,
|
||||
self_properties=undefined, read_write=True):
|
||||
setting_properties=undefined, read_write=True,
|
||||
apply_requires=True):
|
||||
"""
|
||||
"""
|
||||
if opt is None:
|
||||
props = self._p_.getproperties(path, default_properties)
|
||||
else:
|
||||
if self_properties is undefined:
|
||||
self_properties = self._getproperties()
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
if path is None: # pragma: optional cover
|
||||
raise ValueError(_('if opt is not None, path should not be'
|
||||
' None in _getproperties'))
|
||||
is_cached = False
|
||||
if 'cache' in self_properties and 'expire' in self_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
if 'cache' in self_properties and self._p_.hascache(path):
|
||||
is_cached, props = self._p_.getcache(path, ntime)
|
||||
if apply_requires:
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
if 'cache' in setting_properties and self._p_.hascache(path):
|
||||
is_cached, props = self._p_.getcache(path, ntime)
|
||||
if not is_cached:
|
||||
props = copy(self._p_.getproperties(path, opt.impl_getproperties()))
|
||||
props |= self.apply_requires(opt, path)
|
||||
if 'cache' in self_properties:
|
||||
if 'expire' in self_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, props, ntime)
|
||||
props = self._p_.getproperties(path, opt.impl_getproperties())
|
||||
if apply_requires:
|
||||
props = copy(props)
|
||||
props |= self.apply_requires(opt, path, setting_properties)
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, props, ntime)
|
||||
if read_write:
|
||||
return copy(props)
|
||||
else:
|
||||
return props
|
||||
props = copy(props)
|
||||
return props
|
||||
|
||||
def append(self, propname):
|
||||
"puts property propname in the Config's properties attribute"
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
props.add(propname)
|
||||
self._setproperties(props, None)
|
||||
if propname not in props:
|
||||
props.add(propname)
|
||||
self._setproperties(props, None)
|
||||
|
||||
def remove(self, propname):
|
||||
"deletes property propname in the Config's properties attribute"
|
||||
|
@ -422,7 +426,8 @@ class Settings(object):
|
|||
#____________________________________________________________
|
||||
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
|
||||
value=None, force_permissive=False,
|
||||
force_properties=None, force_permissives=None,
|
||||
force_properties=None,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
@ -432,8 +437,6 @@ class Settings(object):
|
|||
was present
|
||||
:param force_properties: set() with properties that is force to add
|
||||
in global properties
|
||||
:param force_permissives: set() with permissives that is force to add
|
||||
in global permissives
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
@ -443,25 +446,26 @@ class Settings(object):
|
|||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
if self_properties is undefined:
|
||||
self_properties = self._getproperties(read_write=False)
|
||||
properties = self._getproperties(opt_or_descr, path,
|
||||
self_properties=self_properties)
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
if self_properties is not undefined:
|
||||
properties = copy(self_properties)
|
||||
else:
|
||||
properties = self._getproperties(opt_or_descr, path,
|
||||
setting_properties=setting_properties)
|
||||
# remove opt permissive
|
||||
# permissive affect option's permission with or without permissive
|
||||
# global property
|
||||
properties -= self._p_.getpermissive(path)
|
||||
# remove global permissive if need
|
||||
if force_permissive is True or 'permissive' in self_properties:
|
||||
if force_permissive is True or 'permissive' in setting_properties:
|
||||
properties -= self._p_.getpermissive()
|
||||
if force_permissives is not None:
|
||||
properties -= force_permissives
|
||||
|
||||
if force_properties is not None:
|
||||
forced_properties = copy(self_properties)
|
||||
forced_properties = copy(setting_properties)
|
||||
forced_properties.update(force_properties)
|
||||
else:
|
||||
forced_properties = self_properties
|
||||
forced_properties = setting_properties
|
||||
|
||||
# calc properties
|
||||
properties &= forced_properties
|
||||
|
@ -531,10 +535,16 @@ class Settings(object):
|
|||
|
||||
#____________________________________________________________
|
||||
def _read(self, remove, append):
|
||||
for prop in remove:
|
||||
self.remove(prop)
|
||||
for prop in append:
|
||||
self.append(prop)
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
modified = False
|
||||
if remove & props != set([]):
|
||||
props = props - remove
|
||||
modified = True
|
||||
if append & props != append:
|
||||
props = props | append
|
||||
modified = True
|
||||
if modified:
|
||||
self._setproperties(props, None)
|
||||
|
||||
def read_only(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
|
@ -555,7 +565,7 @@ class Settings(object):
|
|||
else:
|
||||
self._p_.reset_all_cache()
|
||||
|
||||
def apply_requires(self, opt, path):
|
||||
def apply_requires(self, opt, path, setting_properties):
|
||||
"""carries out the jit (just in time) requirements between options
|
||||
|
||||
a requirement is a tuple of this form that comes from the option's
|
||||
|
@ -616,7 +626,8 @@ class Settings(object):
|
|||
" '{0}' with requirement on: "
|
||||
"'{1}'").format(path, reqpath))
|
||||
try:
|
||||
value = context.getattr(reqpath, force_permissive=True)
|
||||
value = context.getattr(reqpath, force_permissive=True,
|
||||
_setting_properties=setting_properties)
|
||||
except PropertiesOptionError as err:
|
||||
if not transitive:
|
||||
continue
|
||||
|
|
|
@ -55,7 +55,7 @@ class Values(object):
|
|||
return context
|
||||
|
||||
def _getvalue(self, opt, path, is_default, index=undefined,
|
||||
with_meta=True, settings=undefined):
|
||||
with_meta=True, self_properties=undefined):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
|
@ -64,11 +64,11 @@ class Values(object):
|
|||
if opt.impl_is_optiondescription(): # pragma: optional cover
|
||||
raise ValueError(_('optiondescription has no value'))
|
||||
|
||||
if settings is undefined:
|
||||
settings = self._getcontext().cfgimpl_get_settings()._getproperties(
|
||||
if self_properties is undefined:
|
||||
self_properties = self._getcontext().cfgimpl_get_settings()._getproperties(
|
||||
opt, path, read_write=False)
|
||||
force_default = 'frozen' in settings and \
|
||||
'force_default_on_freeze' in settings
|
||||
force_default = 'frozen' in self_properties and \
|
||||
'force_default_on_freeze' in self_properties
|
||||
if not is_default and not force_default:
|
||||
value = self._p_.getvalue(path)
|
||||
if index is not undefined:
|
||||
|
@ -210,27 +210,37 @@ class Values(object):
|
|||
def _get_cached_item(self, opt, path=None, validate=True,
|
||||
force_permissive=False, force_properties=None,
|
||||
validate_properties=True,
|
||||
setting_properties=undefined):
|
||||
setting_properties=undefined, self_properties=undefined):
|
||||
untrusted_cached_properties = force_properties is None
|
||||
context = self._getcontext()
|
||||
if path is None:
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
path = opt.impl_getpath(context)
|
||||
ntime = None
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getcontext().cfgimpl_get_settings(
|
||||
setting_properties = context.cfgimpl_get_settings(
|
||||
)._getproperties(read_write=False)
|
||||
settings = self._getcontext().cfgimpl_get_settings()._getproperties(
|
||||
opt, path, read_write=False, self_properties=setting_properties)
|
||||
if self_properties is undefined:
|
||||
self_properties = context.cfgimpl_get_settings()._getproperties(
|
||||
opt, path, read_write=False, setting_properties=setting_properties)
|
||||
if 'cache' in setting_properties and self._p_.hascache(path):
|
||||
if 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
is_cached, value = self._p_.getcache(path, ntime)
|
||||
if is_cached:
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
#load value so don't need to validate if is not a Multi
|
||||
value = Multi(value, self.context, opt, path)
|
||||
if not untrusted_cached_properties:
|
||||
# revalidate properties (because not default properties)
|
||||
context.cfgimpl_get_settings().validate_properties(opt, False, False, value=value,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties)
|
||||
return value
|
||||
val = self._getitem(opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties,
|
||||
setting_properties, settings=settings)
|
||||
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:
|
||||
|
@ -242,7 +252,7 @@ class Values(object):
|
|||
|
||||
def _getitem(self, opt, path, validate, force_permissive, force_properties,
|
||||
validate_properties, setting_properties=undefined,
|
||||
settings=undefined):
|
||||
self_properties=undefined):
|
||||
if opt.impl_is_master_slaves():
|
||||
return opt.impl_get_master_slaves().getitem(self, opt, path,
|
||||
validate,
|
||||
|
@ -250,20 +260,20 @@ class Values(object):
|
|||
force_properties,
|
||||
validate_properties,
|
||||
setting_properties=setting_properties,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
else:
|
||||
return self._get_validated_value(opt, path, validate,
|
||||
force_permissive,
|
||||
force_properties,
|
||||
validate_properties,
|
||||
setting_properties=setting_properties,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
|
||||
def _get_validated_value(self, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties,
|
||||
index=undefined, submulti_index=undefined,
|
||||
with_meta=True, setting_properties=undefined,
|
||||
settings=undefined):
|
||||
self_properties=undefined):
|
||||
"""same has getitem but don't touch the cache
|
||||
index is None for slave value, if value returned is not a list, just return []
|
||||
"""
|
||||
|
@ -271,12 +281,12 @@ class Values(object):
|
|||
setting = context.cfgimpl_get_settings()
|
||||
if setting_properties is undefined:
|
||||
setting_properties = setting._getproperties(read_write=False)
|
||||
if settings is undefined:
|
||||
settings = setting._getproperties(opt, path, read_write=False)
|
||||
if self_properties is undefined:
|
||||
self_properties = setting._getproperties(opt, path, read_write=False)
|
||||
is_default = self._is_default_owner(opt, path,
|
||||
validate_properties=False,
|
||||
validate_meta=False,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
try:
|
||||
if index is None:
|
||||
gv_index = undefined
|
||||
|
@ -284,7 +294,7 @@ class Values(object):
|
|||
gv_index = index
|
||||
value = self._getvalue(opt, path, is_default, index=gv_index,
|
||||
with_meta=with_meta,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
config_error = None
|
||||
except ConfigError as err:
|
||||
# For calculating properties, we need value (ie for mandatory
|
||||
|
@ -329,7 +339,7 @@ class Values(object):
|
|||
config_error = err
|
||||
value = None
|
||||
|
||||
if is_default and 'force_store_value' in settings:
|
||||
if is_default and 'force_store_value' in self_properties:
|
||||
if isinstance(value, Multi):
|
||||
item = list(value)
|
||||
else:
|
||||
|
@ -337,11 +347,18 @@ class Values(object):
|
|||
self.setitem(opt, item, path, is_write=False,
|
||||
force_permissive=force_permissive)
|
||||
if validate_properties:
|
||||
setting.validate_properties(opt, False, False, value=value,
|
||||
if config_error is not None:
|
||||
# should not raise PropertiesOptionError if option is
|
||||
# mandatory
|
||||
val_props = undefined
|
||||
else:
|
||||
val_props = value
|
||||
setting.validate_properties(opt, False, False, value=val_props,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties,
|
||||
self_properties=setting_properties)
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties)
|
||||
if config_error is not None:
|
||||
raise config_error
|
||||
return value
|
||||
|
@ -385,7 +402,7 @@ class Values(object):
|
|||
setting.validate_properties(opt, False, is_write,
|
||||
value=value, path=path,
|
||||
force_permissive=force_permissive,
|
||||
self_properties=setting_properties)
|
||||
setting_properties=setting_properties)
|
||||
if isinstance(value, Multi):
|
||||
value = list(value)
|
||||
if opt.impl_is_submulti():
|
||||
|
@ -398,8 +415,8 @@ class Values(object):
|
|||
def _is_meta(self, opt, path):
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
settings = setting._getproperties(opt, path, read_write=False)
|
||||
if 'frozen' in settings and 'force_default_on_freeze' in settings:
|
||||
self_properties = setting._getproperties(opt, path, read_write=False)
|
||||
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
|
||||
return False
|
||||
if self._p_.getowner(path, owners.default) is not owners.default:
|
||||
return False
|
||||
|
@ -424,21 +441,21 @@ class Values(object):
|
|||
|
||||
def _getowner(self, opt, path, validate_properties=True,
|
||||
force_permissive=False, validate_meta=undefined,
|
||||
settings=undefined):
|
||||
self_properties=undefined):
|
||||
"""get owner of an option
|
||||
"""
|
||||
if not isinstance(opt, Option) and not isinstance(opt,
|
||||
DynSymLinkOption):
|
||||
raise ConfigError(_('owner only avalaible for an option'))
|
||||
context = self._getcontext()
|
||||
if settings is undefined:
|
||||
settings = context.cfgimpl_get_settings()._getproperties(
|
||||
if self_properties is undefined:
|
||||
self_properties = context.cfgimpl_get_settings()._getproperties(
|
||||
opt, path, read_write=False)
|
||||
if 'frozen' in settings and 'force_default_on_freeze' in settings:
|
||||
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
|
||||
return owners.default
|
||||
if validate_properties:
|
||||
self._getitem(opt, path, True, force_permissive, None, True,
|
||||
settings=settings)
|
||||
self_properties=self_properties)
|
||||
owner = self._p_.getowner(path, owners.default)
|
||||
if validate_meta is undefined:
|
||||
if opt.impl_is_master_slaves('slave'):
|
||||
|
@ -490,10 +507,10 @@ class Values(object):
|
|||
validate_meta=validate_meta)
|
||||
|
||||
def _is_default_owner(self, opt, path, validate_properties=True,
|
||||
validate_meta=True, settings=undefined):
|
||||
validate_meta=True, self_properties=undefined):
|
||||
return self._getowner(opt, path, validate_properties,
|
||||
validate_meta=validate_meta,
|
||||
settings=settings) == \
|
||||
self_properties=self_properties) == \
|
||||
owners.default
|
||||
|
||||
def reset_cache(self, only_expired):
|
||||
|
@ -528,41 +545,72 @@ class Values(object):
|
|||
raise ValueError(_("information's item"
|
||||
" not found: {0}").format(key))
|
||||
|
||||
def mandatory_warnings(self, force_permissive=False):
|
||||
def mandatory_warnings(self, force_permissive=False, validate=True):
|
||||
"""convenience function to trace Options that are mandatory and
|
||||
where no value has been set
|
||||
|
||||
:returns: generator of mandatory Option's path
|
||||
:param force_permissive: do raise with permissives properties
|
||||
:type force_permissive: `bool`
|
||||
:param validate: validate value when calculating properties
|
||||
:type validate: `bool`
|
||||
|
||||
:returns: generator of mandatory Option's path
|
||||
"""
|
||||
def _mandatory_warnings(description):
|
||||
#if value in cache, properties are not calculated
|
||||
_ret = []
|
||||
context = self._getcontext()
|
||||
setting_properties = context.cfgimpl_get_settings()._getproperties(
|
||||
read_write=False)
|
||||
context = self._getcontext()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
setting_properties = context.cfgimpl_get_settings()._getproperties(
|
||||
read_write=False)
|
||||
|
||||
def _mandatory_warnings(description, currpath=None):
|
||||
if currpath is None:
|
||||
currpath = []
|
||||
for opt in description._impl_getchildren(context=context):
|
||||
name = opt.impl_getname()
|
||||
path = '.'.join(currpath + [name])
|
||||
|
||||
if opt.impl_is_optiondescription():
|
||||
_ret.extend(_mandatory_warnings(opt))
|
||||
elif isinstance(opt, SymLinkOption) and \
|
||||
not isinstance(opt, DynSymLinkOption):
|
||||
pass
|
||||
else:
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
try:
|
||||
self._get_cached_item(opt, path=path,
|
||||
force_properties=frozenset(('mandatory',)),
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
settings.validate_properties(opt, True, False, path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype == ['mandatory']:
|
||||
_ret.append(path)
|
||||
return _ret
|
||||
self.reset_cache(False)
|
||||
pass
|
||||
else:
|
||||
for path in _mandatory_warnings(opt, currpath + [name]):
|
||||
yield path
|
||||
else:
|
||||
if isinstance(opt, SymLinkOption) and \
|
||||
not isinstance(opt, DynSymLinkOption):
|
||||
true_opt = opt._impl_getopt()
|
||||
true_path = descr.impl_get_path_by_opt(true_opt)
|
||||
else:
|
||||
true_opt = opt
|
||||
true_path = path
|
||||
#FIXME attention c'est réutilisé donc jamais complet ??
|
||||
self_properties = settings._getproperties(true_opt, true_path,
|
||||
read_write=False,
|
||||
setting_properties=setting_properties)
|
||||
if 'mandatory' in self_properties:
|
||||
try:
|
||||
self._get_cached_item(true_opt, path=true_path,
|
||||
force_properties=frozenset(('mandatory',)),
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties,
|
||||
validate=validate)
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype == ['mandatory']:
|
||||
yield path
|
||||
except ConfigError as err:
|
||||
if validate:
|
||||
raise err
|
||||
else:
|
||||
#assume that uncalculated value is an empty value
|
||||
yield path
|
||||
|
||||
descr = self._getcontext().cfgimpl_get_description()
|
||||
ret = _mandatory_warnings(descr)
|
||||
self.reset_cache(False)
|
||||
return ret
|
||||
for path in _mandatory_warnings(descr):
|
||||
yield path
|
||||
|
||||
def force_cache(self):
|
||||
"""parse all option to force data in cache
|
||||
|
@ -660,7 +708,7 @@ class Multi(list):
|
|||
self._validate(value, fake_context, index, True)
|
||||
#assume not checking mandatory property
|
||||
super(Multi, self).__setitem__(index, value)
|
||||
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, setting_properties=setting_properties)
|
||||
|
||||
#def __repr__(self, *args, **kwargs):
|
||||
# return super(Multi, self).__repr__(*args, **kwargs)
|
||||
|
|
Loading…
Reference in a new issue