refactor
This commit is contained in:
parent
5d1be8a11a
commit
119ca85041
|
@ -220,16 +220,12 @@ def _autocheck_set_value(api, path, **kwargs):
|
|||
submulti_ = api.unrestraint.option(path).option.issubmulti()
|
||||
ismaster = api.unrestraint.option(path).option.ismaster()
|
||||
isslave = api.unrestraint.option(path).option.isslave()
|
||||
# empty_value = _getdefault(api, path, multi, isslave, submulti_)
|
||||
if not multi:
|
||||
first_value = FIRST_VALUE
|
||||
# second_value = SECOND_VALUE
|
||||
elif submulti_ is False:
|
||||
first_value = LIST_FIRST_VALUE
|
||||
# second_value = LIST_SECOND_VALUE
|
||||
else:
|
||||
first_value = SUBLIST_FIRST_VALUE
|
||||
# second_value = SUBLIST_SECOND_VALUE
|
||||
|
||||
# for slave should have an index and good length
|
||||
# for master must append, not set
|
||||
|
@ -509,7 +505,7 @@ def _getproperties(multi, isslave, kwargs):
|
|||
if extra_properties:
|
||||
properties.extend(extra_properties)
|
||||
default_props.extend(extra_properties)
|
||||
return default_props, tuple(properties)
|
||||
return default_props, frozenset(properties)
|
||||
|
||||
|
||||
def _check_default_properties(api, path, kwargs, props_permissive, props):
|
||||
|
@ -540,17 +536,6 @@ def _autocheck_property(api, path, **kwargs):
|
|||
multi = api.unrestraint.option(path).option.ismulti()
|
||||
isslave = api.unrestraint.option(path).option.isslave()
|
||||
|
||||
# define properties
|
||||
properties = copy(PROPERTIES_LIST)
|
||||
if multi and not isslave:
|
||||
default_props = ['empty']
|
||||
properties.append('empty')
|
||||
else:
|
||||
default_props = []
|
||||
extra_properties = kwargs.get('extra_properties')
|
||||
if extra_properties:
|
||||
properties.extend(extra_properties)
|
||||
default_props.extend(extra_properties)
|
||||
default_props, properties = _getproperties(multi, isslave, kwargs)
|
||||
|
||||
_check_default_properties(api, path, kwargs, default_props, default_props)
|
||||
|
@ -863,7 +848,7 @@ def autocheck_permissive(api, path, **kwargs):
|
|||
|
||||
|
||||
|
||||
def check_all(cfg, path, meta, multi, default, default_multi, **kwargs):
|
||||
def check_all(cfg, path, meta, multi, default, default_multi, require, consistency, **kwargs):
|
||||
if DISPLAY:
|
||||
text = u' {} launch tests for {}'.format(ICON, path)
|
||||
if multi is True:
|
||||
|
@ -882,22 +867,37 @@ def check_all(cfg, path, meta, multi, default, default_multi, **kwargs):
|
|||
if api.unrestraint.option(path).option.isslave():
|
||||
master_path = path.rsplit('.', 1)[0] + '.master'
|
||||
api.option(master_path).value.set(LIST_SECOND_VALUE)
|
||||
for func in autocheck_registers:
|
||||
api = getapi(cfg.duplicate())
|
||||
if DISPLAY:
|
||||
print(u' {} {}'.format(ICON, func.__name__))
|
||||
try:
|
||||
func(api, path, **kwargs)
|
||||
except Exception as err:
|
||||
msg = u'error in function {} for {}'.format(func.__name__, path)
|
||||
if multi is True:
|
||||
msg += u' as a multi'
|
||||
elif multi is submulti:
|
||||
msg += u' as a submulti'
|
||||
if multi is True:
|
||||
msg += u' with default value'
|
||||
print(u'{}: {}'.format(msg, kwargs))
|
||||
raise err
|
||||
if not require:
|
||||
requires = [False]
|
||||
else:
|
||||
requires = [False, True]
|
||||
for req in requires:
|
||||
for func in autocheck_registers:
|
||||
api = getapi(cfg.duplicate())
|
||||
#FIXME devrait etre dans la config ca ...
|
||||
api.read_write()
|
||||
ckwargs = copy(kwargs)
|
||||
if req:
|
||||
api.option('extraoptrequire').value.set('value')
|
||||
if 'permissive' in ckwargs and not 'permissive_od' in ckwargs or \
|
||||
'propertyerror' in ckwargs and not 'propertyerror_od' in ckwargs:
|
||||
for to_del in ['permissive', 'propertyerror', 'extra_properties']:
|
||||
if to_del in ckwargs:
|
||||
del ckwargs[to_del]
|
||||
if DISPLAY:
|
||||
print(u' {} {}'.format(ICON, func.__name__))
|
||||
try:
|
||||
func(api, path, **ckwargs)
|
||||
except Exception as err:
|
||||
msg = u'error in function {} for {}'.format(func.__name__, path)
|
||||
if multi is True:
|
||||
msg += u' as a multi'
|
||||
elif multi is submulti:
|
||||
msg += u' as a submulti'
|
||||
if multi is True:
|
||||
msg += u' with default value'
|
||||
print(u'{}: {}'.format(msg, ckwargs))
|
||||
raise err
|
||||
|
||||
|
||||
def check_deref(weakrefs):
|
||||
|
@ -907,23 +907,32 @@ def check_deref(weakrefs):
|
|||
assert wrf() is None
|
||||
|
||||
|
||||
def make_conf(options, meta, multi, default, default_multi):
|
||||
def make_conf(options, meta, multi, default, default_multi, require, consistency):
|
||||
weakrefs = []
|
||||
dyn = []
|
||||
goptions = []
|
||||
def make_option(path, option_infos):
|
||||
#FIXME
|
||||
option_type = 'str'
|
||||
option_properties = []
|
||||
option_requires = []
|
||||
isslave = False
|
||||
if option_infos is not None:
|
||||
for prop in PROPERTIES:
|
||||
if option_infos.get(prop, False) is True:
|
||||
option_properties.append(prop)
|
||||
if not require:
|
||||
option_properties.append(prop)
|
||||
else:
|
||||
option_requires.append({'option': goptions[0], 'expected': None,
|
||||
'action': prop})
|
||||
isslave = option_infos.get('slave', False)
|
||||
args = [path, "{}'s option".format(path)]
|
||||
kwargs = {}
|
||||
if option_properties != []:
|
||||
kwargs['properties'] = tuple(option_properties)
|
||||
if multi:
|
||||
if option_requires != []:
|
||||
kwargs['requires'] = option_requires
|
||||
if multi and path is not 'extraoptrequire':
|
||||
kwargs['multi'] = multi
|
||||
if default and not submulti:
|
||||
if multi is False:
|
||||
|
@ -933,7 +942,7 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
else:
|
||||
value = SUBLIST_EMPTY_VALUE
|
||||
kwargs['default'] = value
|
||||
if default_multi:
|
||||
if default_multi and path is not 'extraoptrequire':
|
||||
if multi is not submulti:
|
||||
value = SECOND_VALUE
|
||||
else:
|
||||
|
@ -942,6 +951,12 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
|
||||
tiramisu_option = OPTIONS_TYPE[option_type]['option']
|
||||
obj = tiramisu_option(*args, **kwargs)
|
||||
if not 'extraopt' in path and consistency:
|
||||
if require:
|
||||
gopt = goptions[1]
|
||||
else:
|
||||
gopt = goptions[0]
|
||||
obj.impl_add_consistency('not_equal', gopt, warnings_only=True)
|
||||
weakrefs.append(weakref.ref(obj))
|
||||
return obj
|
||||
|
||||
|
@ -961,6 +976,7 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
if infos.get('dyn', False) is True:
|
||||
optiondescription = DynOptionDescription
|
||||
kwargs['callback'] = return_list
|
||||
dyn.append(path)
|
||||
options = []
|
||||
if 'options' in collected:
|
||||
options.extend(collected['options'])
|
||||
|
@ -978,7 +994,22 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
return obj
|
||||
|
||||
collect_options = {}
|
||||
for path, option in options.items():
|
||||
if require or consistency:
|
||||
noptions = OrderedDict()
|
||||
if require:
|
||||
noptions['extraoptrequire'] = {}
|
||||
if consistency:
|
||||
subpath = list(options.keys())[0]
|
||||
if '.' in subpath:
|
||||
subpath = subpath.rsplit('.', 1)[0] + '.'
|
||||
else:
|
||||
subpath = ''
|
||||
noptions[subpath + 'extraoptconsistency'] = {}
|
||||
noptions.update(options)
|
||||
else:
|
||||
noptions = options
|
||||
|
||||
for path, option in noptions.items():
|
||||
if option is None:
|
||||
continue
|
||||
local_collect_options = collect_options
|
||||
|
@ -987,8 +1018,9 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
local_collect_options = local_collect_options[optiondescription]
|
||||
local_collect_options['properties'].update(option.get(optiondescription, {}))
|
||||
option_name = path.split('.')[-1]
|
||||
path = '.'.join(path.split('.')[:-1])
|
||||
local_collect_options.setdefault('options', []).append(make_option(option_name, option.get(option_name)))
|
||||
obj = make_option(option_name, option.get(option_name))
|
||||
goptions.append(obj)
|
||||
local_collect_options.setdefault('options', []).append(obj)
|
||||
|
||||
rootod = make_optiondescriptions('root', collect_options)
|
||||
if rootod is None:
|
||||
|
@ -998,7 +1030,8 @@ def make_conf(options, meta, multi, default, default_multi):
|
|||
if meta:
|
||||
cfg = MetaConfig([cfg], session_id='metatest')
|
||||
weakrefs.append(weakref.ref(cfg))
|
||||
return cfg, weakrefs
|
||||
del goptions
|
||||
return cfg, weakrefs, dyn
|
||||
|
||||
|
||||
DICT_PATHS = [
|
||||
|
@ -1091,24 +1124,35 @@ def test_options(paths):
|
|||
return kwargs
|
||||
|
||||
lpaths = list(paths.keys())
|
||||
for meta in (False, True):
|
||||
for default_multi in (False, True):
|
||||
for default in (False, True):
|
||||
for multi in (False, True, submulti):
|
||||
if multi is False and default_multi:
|
||||
continue
|
||||
cfg, weakrefs = make_conf(paths, meta, multi, default, default_multi)
|
||||
if cfg is None:
|
||||
continue
|
||||
if len(lpaths) == 9:
|
||||
check_all(cfg, lpaths[3], meta, multi, default, default_multi, **get_kwargs(lpaths[0]))
|
||||
check_all(cfg, lpaths[4], meta, multi, default, default_multi, **get_kwargs(lpaths[1]))
|
||||
check_all(cfg, lpaths[5], meta, multi, default, default_multi, **get_kwargs(lpaths[2]))
|
||||
check_all(cfg, lpaths[6], meta, multi, default, default_multi, **get_kwargs(lpaths[0]))
|
||||
check_all(cfg, lpaths[7], meta, multi, default, default_multi, **get_kwargs(lpaths[1]))
|
||||
check_all(cfg, lpaths[8], meta, multi, default, default_multi, **get_kwargs(lpaths[2]))
|
||||
else:
|
||||
for lpath in lpaths:
|
||||
check_all(cfg, lpath, meta, multi, default, default_multi, **get_kwargs(lpath))
|
||||
del cfg
|
||||
check_deref(weakrefs)
|
||||
meta = False
|
||||
#for meta in (False, True):
|
||||
for consistency in (False, True):
|
||||
for require in (False, True):
|
||||
for default_multi in (False, True):
|
||||
for default in (False, True):
|
||||
for multi in (False, True, submulti):
|
||||
if multi is submulti and consistency:
|
||||
continue
|
||||
if multi is False and default_multi:
|
||||
continue
|
||||
cfg, weakrefs, dyn = make_conf(paths, meta, multi, default, default_multi, require, consistency)
|
||||
if cfg is None:
|
||||
continue
|
||||
if dyn:
|
||||
cnt = 0
|
||||
idx = 0
|
||||
for index, lpath in enumerate(lpaths):
|
||||
if paths[lpath]:
|
||||
cnt += 1
|
||||
else:
|
||||
check_all(cfg, lpaths[index], meta, multi, default,
|
||||
default_multi, require, consistency, **get_kwargs(lpaths[idx]))
|
||||
idx += 1
|
||||
if idx == cnt:
|
||||
idx = 0
|
||||
else:
|
||||
for lpath in lpaths:
|
||||
check_all(cfg, lpath, meta, multi, default,
|
||||
default_multi, require, consistency, **get_kwargs(lpath))
|
||||
del cfg
|
||||
check_deref(weakrefs)
|
||||
|
|
|
@ -145,6 +145,7 @@ class TiramisuOptionOwner(CommonTiramisuOption):
|
|||
setting_properties,
|
||||
force_permissive,
|
||||
force_unrestraint):
|
||||
|
||||
super(TiramisuOptionOwner, self).__init__(opt,
|
||||
path,
|
||||
index,
|
||||
|
@ -158,12 +159,16 @@ class TiramisuOptionOwner(CommonTiramisuOption):
|
|||
def get(self):
|
||||
"""get owner for a specified option"""
|
||||
return self.values.getowner(self.opt,
|
||||
self.path,
|
||||
self.setting_properties,
|
||||
index=self.index,
|
||||
force_permissive=self.force_permissive)
|
||||
|
||||
def isdefault(self):
|
||||
"""is option has defaut value"""
|
||||
return self.values.is_default_owner(self.opt,
|
||||
self.path,
|
||||
self.setting_properties,
|
||||
index=self.index,
|
||||
force_permissive=self.force_permissive)
|
||||
|
||||
|
@ -174,10 +179,9 @@ class TiramisuOptionOwner(CommonTiramisuOption):
|
|||
except AttributeError:
|
||||
owners.addowner(owner)
|
||||
obj_owner = getattr(owners, owner)
|
||||
self.values.setowner(self.opt,
|
||||
self.values.setowner(self.path,
|
||||
obj_owner,
|
||||
self.index,
|
||||
force_permissive=self.force_permissive)
|
||||
self.index)
|
||||
|
||||
|
||||
class TiramisuOptionProperty(CommonTiramisuOption):
|
||||
|
@ -207,14 +211,14 @@ class TiramisuOptionProperty(CommonTiramisuOption):
|
|||
self._test_slave_index()
|
||||
return self.settings.getproperties(self.opt,
|
||||
self.path,
|
||||
index=self.index,
|
||||
obj=False)
|
||||
self.setting_properties,
|
||||
index=self.index)
|
||||
|
||||
def set(self, properties):
|
||||
"""set properties for a specified option"""
|
||||
self.settings.setproperties(set(properties),
|
||||
self.opt,
|
||||
self.path)
|
||||
self.settings.setproperties(self.opt,
|
||||
self.path,
|
||||
properties)
|
||||
|
||||
def reset(self):
|
||||
"""reset all personalised properties
|
||||
|
@ -247,16 +251,17 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
|
|||
|
||||
def get(self):
|
||||
"""get permissive value for a specified path"""
|
||||
return self.settings.getpermissive(self.setting_properties, self.path)
|
||||
return self.settings.getpermissive(self.path)
|
||||
|
||||
def set(self, permissive):
|
||||
self.settings.setpermissive(permissive, opt=self.opt, path=self.path)
|
||||
self.settings.setpermissive(self.opt,
|
||||
self.path,
|
||||
permissive)
|
||||
|
||||
#def reset(self, path):
|
||||
# """reset all personalised properties
|
||||
# """
|
||||
# self._get_obj_by_path(path)
|
||||
# self.settings.reset(_path=path)
|
||||
def reset(self, path):
|
||||
"""reset all personalised permissive
|
||||
"""
|
||||
self.set(tuple())
|
||||
|
||||
|
||||
class TiramisuOptionValue(CommonTiramisuOption):
|
||||
|
@ -409,11 +414,6 @@ class TiramisuAPI(object):
|
|||
self.config = config
|
||||
self.force_permissive = force_permissive
|
||||
self.force_unrestraint = force_unrestraint
|
||||
settings = self.config.cfgimpl_get_settings()
|
||||
# #FIXME ?
|
||||
self.config.read_write()
|
||||
settings.setpermissive(('hidden',))
|
||||
#/FIXME ?
|
||||
|
||||
def option(self, path, index=None):
|
||||
validate = not self.force_unrestraint
|
||||
|
@ -464,6 +464,16 @@ class TiramisuAPI(object):
|
|||
txt.append(module(None, None).help)
|
||||
return '\n'.join(txt)
|
||||
|
||||
def read_only(self):
|
||||
self.config.read_write()
|
||||
|
||||
def read_write(self):
|
||||
settings = self.config.cfgimpl_get_settings()
|
||||
self.config.read_write()
|
||||
# #FIXME ?
|
||||
settings.set_context_permissive(frozenset(['hidden']))
|
||||
#/FIXME ?
|
||||
|
||||
|
||||
def getapi(config):
|
||||
"""instanciate TiramisuAPI
|
||||
|
|
|
@ -90,31 +90,39 @@ class SubConfig(object):
|
|||
def cfgimpl_get_length(self):
|
||||
return self._impl_length
|
||||
|
||||
def reset_one_option_cache(self, values, settings, resetted_opts, opt, only):
|
||||
if 'values' in only:
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt, values, 'values', tresetted_opts)
|
||||
|
||||
if 'settings' in only:
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt, settings, 'settings', tresetted_opts)
|
||||
else:
|
||||
if 'properties' in only:
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt, settings, 'properties', tresetted_opts)
|
||||
if 'permissives' in only:
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt, settings, 'permissives', tresetted_opts)
|
||||
def reset_one_option_cache(self,
|
||||
values,
|
||||
settings,
|
||||
resetted_opts,
|
||||
opt,
|
||||
path):
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt,
|
||||
path,
|
||||
values,
|
||||
'values',
|
||||
tresetted_opts)
|
||||
tresetted_opts = copy(resetted_opts)
|
||||
opt.reset_cache(opt,
|
||||
path,
|
||||
settings,
|
||||
'settings',
|
||||
tresetted_opts)
|
||||
resetted_opts |= tresetted_opts
|
||||
for option in opt._get_dependencies(self):
|
||||
for woption in opt._get_dependencies(self):
|
||||
option = woption()
|
||||
if option in resetted_opts:
|
||||
continue
|
||||
self.reset_one_option_cache(values, settings, resetted_opts, option(), only)
|
||||
del(option)
|
||||
option_path = opt.impl_getpath(self)
|
||||
self.reset_one_option_cache(values,
|
||||
settings,
|
||||
resetted_opts,
|
||||
option,
|
||||
option_path)
|
||||
del option
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
only=('values', 'properties', 'permissives', 'settings'),
|
||||
opt=None,
|
||||
path=None,
|
||||
resetted_opts=None):
|
||||
|
@ -127,33 +135,19 @@ class SubConfig(object):
|
|||
def reset_expired_cache():
|
||||
# reset cache for expired cache value ony
|
||||
datetime = int(time())
|
||||
if 'values' in only:
|
||||
values._p_.reset_expired_cache(datetime)
|
||||
if 'settings' in only or 'properties' in only:
|
||||
settings._p_.reset_expired_cache(datetime)
|
||||
if 'settings' in only or 'permissives' in only:
|
||||
settings._pp_.reset_expired_cache(datetime)
|
||||
values._p_.reset_expired_cache(datetime)
|
||||
settings._p_.reset_expired_cache(datetime)
|
||||
|
||||
def reset_all_cache():
|
||||
if 'values' in only:
|
||||
values._p_.reset_all_cache()
|
||||
if 'settings' in only:
|
||||
settings._p_.reset_all_cache()
|
||||
settings._pp_.reset_all_cache()
|
||||
else:
|
||||
if 'properties' in only:
|
||||
settings._p_.reset_all_cache()
|
||||
if 'permissives' in only:
|
||||
settings._pp_.reset_all_cache()
|
||||
values._p_.reset_all_cache()
|
||||
settings._p_.reset_all_cache()
|
||||
|
||||
if resetted_opts is None:
|
||||
resetted_opts = set()
|
||||
|
||||
context = self._cfgimpl_get_context()
|
||||
if 'values' in only:
|
||||
values = context.cfgimpl_get_values()
|
||||
if 'settings' in only or 'properties' in only or 'permissives' in only:
|
||||
settings = context.cfgimpl_get_settings()
|
||||
values = context.cfgimpl_get_values()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
|
||||
if not None in (opt, path):
|
||||
if opt not in resetted_opts:
|
||||
|
@ -161,7 +155,7 @@ class SubConfig(object):
|
|||
settings,
|
||||
resetted_opts,
|
||||
opt,
|
||||
only)
|
||||
path)
|
||||
|
||||
elif only_expired:
|
||||
reset_expired_cache()
|
||||
|
@ -308,7 +302,6 @@ class SubConfig(object):
|
|||
name,
|
||||
value,
|
||||
force_permissive=False,
|
||||
not_raises=False,
|
||||
index=None,
|
||||
setting_properties=undefined,
|
||||
_commit=True):
|
||||
|
@ -319,7 +312,7 @@ class SubConfig(object):
|
|||
value)
|
||||
context = self._cfgimpl_get_context()
|
||||
if setting_properties is undefined:
|
||||
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
|
||||
setting_properties = context.cfgimpl_get_settings().get_context_properties()
|
||||
if '.' in name: # pragma: optional cover
|
||||
self, name = self.cfgimpl_get_home_by_path(name,
|
||||
force_permissive=force_permissive,
|
||||
|
@ -332,21 +325,17 @@ class SubConfig(object):
|
|||
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
|
||||
raise TypeError(_("can't assign to a SymlinkOption"))
|
||||
else:
|
||||
msg = self.cfgimpl_get_description().impl_validate_value(child, value, self)
|
||||
if msg is not None:
|
||||
if not_raises:
|
||||
return msg
|
||||
else:
|
||||
raise msg
|
||||
self.cfgimpl_get_description().impl_validate_value(child,
|
||||
value,
|
||||
self)
|
||||
subpath = self._get_subpath(name)
|
||||
return self.cfgimpl_get_values().setitem(child,
|
||||
value,
|
||||
subpath,
|
||||
force_permissive,
|
||||
not_raises,
|
||||
index,
|
||||
setting_properties,
|
||||
_commit)
|
||||
return self.cfgimpl_get_values().setvalue(child,
|
||||
value,
|
||||
subpath,
|
||||
force_permissive,
|
||||
index,
|
||||
setting_properties,
|
||||
_commit)
|
||||
|
||||
def __delattr__(self, name):
|
||||
self.delattr(name)
|
||||
|
@ -467,12 +456,12 @@ class SubConfig(object):
|
|||
index=index)
|
||||
elif option.impl_is_optiondescription():
|
||||
if setting_properties:
|
||||
props = self.cfgimpl_get_settings().validate_properties(option,
|
||||
True,
|
||||
False,
|
||||
path=subpath,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
self.cfgimpl_get_settings().validate_properties(option,
|
||||
True,
|
||||
False,
|
||||
path=subpath,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
if returns_option is True:
|
||||
return option
|
||||
return SubConfig(option,
|
||||
|
@ -618,7 +607,7 @@ class SubConfig(object):
|
|||
fullpath=False):
|
||||
"""exports the whole config into a `dict`, for example:
|
||||
|
||||
>>> print cfg.make_dict()
|
||||
>>> print(cfg.make_dict())
|
||||
{'od2.var4': None, 'od2.var5': None, 'od2.var6': None}
|
||||
|
||||
|
||||
|
@ -626,13 +615,13 @@ class SubConfig(object):
|
|||
:param flatten: returns a dict(name=value) instead of a dict(path=value)
|
||||
::
|
||||
|
||||
>>> print cfg.make_dict(flatten=True)
|
||||
>>> print(cfg.make_dict(flatten=True))
|
||||
{'var5': None, 'var4': None, 'var6': None}
|
||||
|
||||
:param withoption: returns the options that are present in the very same
|
||||
`OptionDescription` than the `withoption` itself::
|
||||
|
||||
>>> print cfg.make_dict(withoption='var1')
|
||||
>>> print(cfg.make_dict(withoption='var1'))
|
||||
{'od2.var4': None, 'od2.var5': None,
|
||||
'od2.var6': None,
|
||||
'od2.var1': u'value',
|
||||
|
@ -643,8 +632,8 @@ class SubConfig(object):
|
|||
:param withvalue: returns the options that have the value `withvalue`
|
||||
::
|
||||
|
||||
>>> print c.make_dict(withoption='var1',
|
||||
withvalue=u'value')
|
||||
>>> print(c.make_dict(withoption='var1',
|
||||
withvalue=u'value'))
|
||||
{'od2.var4': None,
|
||||
'od2.var5': None,
|
||||
'od2.var6': None,
|
||||
|
@ -798,14 +787,12 @@ class _CommonConfig(SubConfig):
|
|||
else:
|
||||
if index is None and option.impl_is_master_slaves('slave'):
|
||||
subpath = self._get_subpath(path)
|
||||
props = self.cfgimpl_get_settings().validate_properties(option,
|
||||
True,
|
||||
False,
|
||||
path=subpath,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
if props:
|
||||
raise props
|
||||
self.cfgimpl_get_settings().validate_properties(option,
|
||||
True,
|
||||
False,
|
||||
path=subpath,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties)
|
||||
return option
|
||||
else:
|
||||
return self.getattr(path,
|
||||
|
@ -975,19 +962,16 @@ class GroupConfig(_CommonConfig):
|
|||
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
only=('values', 'settings'),
|
||||
opt=None,
|
||||
path=None,
|
||||
resetted_opts=set()):
|
||||
if isinstance(self, MetaConfig):
|
||||
super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired,
|
||||
only=only,
|
||||
opt=opt,
|
||||
path=path,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
for child in self._impl_children:
|
||||
child.cfgimpl_reset_cache(only_expired=only_expired,
|
||||
only=only,
|
||||
opt=opt,
|
||||
path=path,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
|
|
|
@ -155,7 +155,7 @@ class ValueWarning(UserWarning): # pragma: optional cover
|
|||
...
|
||||
>>> w[0].message.opt == s
|
||||
True
|
||||
>>> print str(w[0].message)
|
||||
>>> print(str(w[0].message))
|
||||
invalid value val for option s: pouet
|
||||
"""
|
||||
def __init__(self, msg, opt):
|
||||
|
|
|
@ -32,7 +32,7 @@ if sys.version_info[0] >= 3: # pragma: no cover
|
|||
else:
|
||||
from inspect import getargspec
|
||||
|
||||
STATIC_TUPLE = tuple()
|
||||
STATIC_TUPLE = frozenset()
|
||||
|
||||
|
||||
submulti = 2
|
||||
|
@ -145,6 +145,8 @@ class Base(object):
|
|||
requires = undefined
|
||||
if properties is None:
|
||||
properties = tuple()
|
||||
if is_multi and 'empty' not in properties:
|
||||
properties = tuple(list(properties) + ['empty'])
|
||||
if not isinstance(properties, tuple):
|
||||
raise TypeError(_('invalid properties type {0} for {1},'
|
||||
' must be a tuple').format(
|
||||
|
@ -406,11 +408,15 @@ class BaseOption(Base):
|
|||
name = name.encode('utf8')
|
||||
return name
|
||||
|
||||
def reset_cache(self, opt, obj, type_, resetted_opts):
|
||||
def reset_cache(self,
|
||||
opt,
|
||||
path,
|
||||
obj,
|
||||
type_,
|
||||
resetted_opts):
|
||||
if opt in resetted_opts:
|
||||
return
|
||||
if not type_ == 'values' or not opt.impl_is_optiondescription():
|
||||
path = opt.impl_getpath(obj._getcontext())
|
||||
if type_ != 'permissives':
|
||||
obj._p_.delcache(path)
|
||||
if type_ in ['settings', 'permissives']:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
# ____________________________________________________________
|
||||
import warnings
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
from .baseoption import OnlyOption, submulti, DynSymLinkOption, validate_callback, STATIC_TUPLE
|
||||
from ..i18n import _
|
||||
|
@ -146,9 +147,17 @@ class Option(OnlyOption):
|
|||
def impl_is_multi(self):
|
||||
return getattr(self, '_multi', 1) != 1
|
||||
|
||||
def _launch_consistency(self, current_opt, func, option, value, context,
|
||||
index, submulti_index, opts, warnings_only,
|
||||
transitive):
|
||||
def _launch_consistency(self,
|
||||
current_opt,
|
||||
func,
|
||||
option,
|
||||
value,
|
||||
context,
|
||||
index,
|
||||
opts,
|
||||
warnings_only,
|
||||
transitive,
|
||||
setting_properties):
|
||||
"""Launch consistency now
|
||||
|
||||
:param func: function name, this name should start with _cons_
|
||||
|
@ -174,7 +183,8 @@ class Option(OnlyOption):
|
|||
all_cons_vals = []
|
||||
all_cons_opts = []
|
||||
val_consistencies = True
|
||||
for opt in opts:
|
||||
for wopt in opts:
|
||||
opt = wopt()
|
||||
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
|
||||
option == opt:
|
||||
# option is current option
|
||||
|
@ -195,7 +205,9 @@ class Option(OnlyOption):
|
|||
else:
|
||||
_index = index
|
||||
try:
|
||||
opt_value = context.getattr(path, validate=False,
|
||||
opt_value = context.getattr(path,
|
||||
setting_properties,
|
||||
validate=False,
|
||||
index=_index,
|
||||
force_permissive=True)
|
||||
except PropertiesOptionError as err:
|
||||
|
@ -254,7 +266,6 @@ class Option(OnlyOption):
|
|||
context=undefined,
|
||||
validate=True,
|
||||
force_index=None,
|
||||
force_submulti_index=None,
|
||||
current_opt=undefined,
|
||||
is_multi=None,
|
||||
display_error=True,
|
||||
|
@ -270,9 +281,6 @@ class Option(OnlyOption):
|
|||
:param force_index: if multi, value has to be a list
|
||||
not if force_index is not None
|
||||
:type force_index: integer
|
||||
:param force_submulti_index: if submulti, value has to be a list
|
||||
not if force_submulti_index is not None
|
||||
:type force_submulti_index: integer
|
||||
"""
|
||||
if not validate:
|
||||
return
|
||||
|
@ -287,10 +295,12 @@ class Option(OnlyOption):
|
|||
if display_error and self.impl_is_unique() and len(set(value)) != len(value):
|
||||
for idx, val in enumerate(value):
|
||||
if val in value[idx+1:]:
|
||||
return ValueError(_('invalid value "{}", this value is already in "{}"').format(
|
||||
val, self.impl_get_display_name()))
|
||||
return ValueError(_('invalid value "{}", this value is already in "{}"'
|
||||
'').format(val,
|
||||
self.impl_get_display_name()))
|
||||
|
||||
def calculation_validator(val, _index):
|
||||
def calculation_validator(val,
|
||||
_index):
|
||||
validator, validator_params = self.impl_get_validator()
|
||||
if validator is not None:
|
||||
if validator_params != {}:
|
||||
|
@ -316,9 +326,10 @@ class Option(OnlyOption):
|
|||
if isinstance(value, Exception):
|
||||
return value
|
||||
|
||||
def do_validation(_value, _index, submulti_index):
|
||||
def do_validation(_value,
|
||||
_index):
|
||||
if _value is None:
|
||||
error = warning = None
|
||||
error = None
|
||||
else:
|
||||
if display_error:
|
||||
# option validation
|
||||
|
@ -327,35 +338,41 @@ class Option(OnlyOption):
|
|||
current_opt)
|
||||
if err:
|
||||
if debug: # pragma: no cover
|
||||
log.debug('do_validation: value: {0}, index: {1}, '
|
||||
'submulti_index: {2}'.format(_value,
|
||||
_index,
|
||||
submulti_index),
|
||||
log.debug('do_validation: value: {0}, index: {1}:'
|
||||
' {2}'.format(_value,
|
||||
_index),
|
||||
exc_info=True)
|
||||
err_msg = '{0}'.format(err)
|
||||
if err_msg:
|
||||
msg = _('"{0}" is an invalid {1} for "{2}", {3}'
|
||||
'').format(_value, self._display_name,
|
||||
'').format(_value,
|
||||
self._display_name,
|
||||
self.impl_get_display_name(), err_msg)
|
||||
else:
|
||||
msg = _('"{0}" is an invalid {1} for "{2}"'
|
||||
'').format(_value, self._display_name,
|
||||
'').format(_value,
|
||||
self._display_name,
|
||||
self.impl_get_display_name())
|
||||
return ValueError(msg)
|
||||
error = None
|
||||
is_warnings_only = getattr(self, '_warnings_only', False)
|
||||
if ((display_error and not is_warnings_only) or
|
||||
(display_warnings and is_warnings_only)):
|
||||
error = calculation_validator(_value, _index)
|
||||
error = calculation_validator(_value,
|
||||
_index)
|
||||
if not error:
|
||||
error = self._second_level_validation(_value, is_warnings_only)
|
||||
error = self._second_level_validation(_value,
|
||||
is_warnings_only)
|
||||
if error:
|
||||
if debug: # pragma: no cover
|
||||
log.debug(_('do_validation for {0}: error in value').format(
|
||||
self.impl_getname()), exc_info=True)
|
||||
if is_warnings_only:
|
||||
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}').format(
|
||||
_value, self._display_name, self.impl_get_display_name(), error)
|
||||
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}'
|
||||
'').format(_value,
|
||||
self._display_name,
|
||||
self.impl_get_display_name(),
|
||||
error)
|
||||
warnings.warn_explicit(ValueWarning(msg, self),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
|
@ -367,9 +384,9 @@ class Option(OnlyOption):
|
|||
_value,
|
||||
context,
|
||||
_index,
|
||||
submulti_index,
|
||||
display_warnings,
|
||||
display_error)
|
||||
display_error,
|
||||
setting_properties)
|
||||
if isinstance(ret, ValueError):
|
||||
error = ret
|
||||
elif ret:
|
||||
|
@ -390,22 +407,22 @@ class Option(OnlyOption):
|
|||
is_multi = self.impl_is_multi()
|
||||
|
||||
if not is_multi:
|
||||
return do_validation(value, None, None)
|
||||
return do_validation(value, None)
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti() and force_submulti_index is None:
|
||||
if self.impl_is_submulti():
|
||||
err = _is_not_unique(value)
|
||||
if err:
|
||||
return err
|
||||
if not isinstance(value, list):
|
||||
return ValueError(_('invalid value "{0}" for "{1}" which'
|
||||
' must be a list').format(
|
||||
value, self.impl_get_display_name()))
|
||||
value, self.impl_get_display_name()))
|
||||
for idx, val in enumerate(value):
|
||||
if isinstance(val, list): # pragma: no cover
|
||||
return ValueError(_('invalid value "{}" for "{}" '
|
||||
'which must not be a list').format(val,
|
||||
self.impl_get_display_name()))
|
||||
err = do_validation(val, force_index, idx)
|
||||
self.impl_get_display_name()))
|
||||
err = do_validation(val, force_index)
|
||||
if err:
|
||||
return err
|
||||
else:
|
||||
|
@ -419,12 +436,12 @@ class Option(OnlyOption):
|
|||
return ValueError(_('invalid value "{}", this value is already'
|
||||
' in "{}"').format(value,
|
||||
self.impl_get_display_name()))
|
||||
return do_validation(value, force_index, force_submulti_index)
|
||||
return do_validation(value, force_index)
|
||||
elif not isinstance(value, list):
|
||||
return ValueError(_('invalid value "{0}" for "{1}" which '
|
||||
'must be a list').format(value,
|
||||
self.impl_getname()))
|
||||
elif self.impl_is_submulti() and force_submulti_index is None:
|
||||
elif self.impl_is_submulti():
|
||||
for idx, val in enumerate(value):
|
||||
err = _is_not_unique(val)
|
||||
if err:
|
||||
|
@ -434,8 +451,9 @@ class Option(OnlyOption):
|
|||
'which must be a list of list'
|
||||
'').format(val,
|
||||
self.impl_getname()))
|
||||
for slave_idx, slave_val in enumerate(val):
|
||||
err = do_validation(slave_val, idx, slave_idx)
|
||||
for slave_val in val:
|
||||
err = do_validation(slave_val,
|
||||
idx)
|
||||
if err:
|
||||
return err
|
||||
else:
|
||||
|
@ -443,16 +461,17 @@ class Option(OnlyOption):
|
|||
if err:
|
||||
return err
|
||||
for idx, val in enumerate(value):
|
||||
err = do_validation(val, idx, force_submulti_index)
|
||||
err = do_validation(val,
|
||||
idx)
|
||||
if err:
|
||||
return err
|
||||
return self._valid_consistency(current_opt,
|
||||
None,
|
||||
context,
|
||||
None,
|
||||
None,
|
||||
display_warnings,
|
||||
display_error)
|
||||
display_error,
|
||||
setting_properties)
|
||||
|
||||
def impl_is_dynsymlinkoption(self):
|
||||
return False
|
||||
|
@ -480,7 +499,10 @@ class Option(OnlyOption):
|
|||
"accesses the Option's doc"
|
||||
return self.impl_get_information('doc')
|
||||
|
||||
def _valid_consistencies(self, other_opts, init=True, func=None):
|
||||
def _valid_consistencies(self,
|
||||
other_opts,
|
||||
init=True,
|
||||
func=None):
|
||||
if self._is_subdyn():
|
||||
dynod = self._subdyn()
|
||||
else:
|
||||
|
@ -488,7 +510,11 @@ class Option(OnlyOption):
|
|||
if self.impl_is_submulti():
|
||||
raise ConfigError(_('cannot add consistency with submulti option'))
|
||||
is_multi = self.impl_is_multi()
|
||||
for opt in other_opts:
|
||||
for wopt in other_opts:
|
||||
if isinstance(wopt, weakref.ReferenceType):
|
||||
opt = wopt()
|
||||
else:
|
||||
opt = wopt
|
||||
if opt.impl_is_submulti():
|
||||
raise ConfigError(_('cannot add consistency with submulti option'))
|
||||
if not isinstance(opt, Option):
|
||||
|
@ -515,7 +541,10 @@ class Option(OnlyOption):
|
|||
if func != 'not_equal':
|
||||
opt._has_dependency = True
|
||||
|
||||
def impl_add_consistency(self, func, *other_opts, **params):
|
||||
def impl_add_consistency(self,
|
||||
func,
|
||||
*other_opts,
|
||||
**params):
|
||||
"""Add consistency means that value will be validate with other_opts
|
||||
option's values.
|
||||
|
||||
|
@ -530,34 +559,46 @@ class Option(OnlyOption):
|
|||
" read-only").format(
|
||||
self.__class__.__name__,
|
||||
self.impl_getname()))
|
||||
self._valid_consistencies(other_opts, func=func)
|
||||
self._valid_consistencies(other_opts,
|
||||
func=func)
|
||||
func = '_cons_{0}'.format(func)
|
||||
if func not in dir(self):
|
||||
raise ConfigError(_('consistency {0} not available for this option').format(func))
|
||||
all_cons_opts = tuple([self] + list(other_opts))
|
||||
options = [weakref.ref(self)]
|
||||
for option in other_opts:
|
||||
options.append(weakref.ref(option))
|
||||
all_cons_opts = tuple(options)
|
||||
unknown_params = set(params.keys()) - set(['warnings_only', 'transitive'])
|
||||
if unknown_params != set():
|
||||
raise ValueError(_('unknown parameter {0} in consistency').format(unknown_params))
|
||||
self._add_consistency(func, all_cons_opts, params)
|
||||
self._add_consistency(func,
|
||||
all_cons_opts,
|
||||
params)
|
||||
#validate default value when add consistency
|
||||
err = self.impl_validate(self.impl_getdefault())
|
||||
if err:
|
||||
self._del_consistency()
|
||||
raise err
|
||||
if func in ALLOWED_CONST_LIST:
|
||||
for opt in all_cons_opts:
|
||||
if getattr(opt, '_unique', undefined) == undefined:
|
||||
opt._unique = True
|
||||
if func != '_cons_not_equal':
|
||||
#consistency could generate warnings or errors
|
||||
self._has_dependency = True
|
||||
for opt in all_cons_opts:
|
||||
for wopt in all_cons_opts:
|
||||
opt = wopt()
|
||||
if func in ALLOWED_CONST_LIST:
|
||||
if getattr(opt, '_unique', undefined) == undefined:
|
||||
opt._unique = True
|
||||
if opt != self:
|
||||
self._add_dependency(opt)
|
||||
opt._add_dependency(self)
|
||||
|
||||
def _valid_consistency(self, option, value, context, index, submulti_idx,
|
||||
display_warnings, display_error):
|
||||
def _valid_consistency(self,
|
||||
option,
|
||||
value,
|
||||
context,
|
||||
index,
|
||||
display_warnings,
|
||||
display_error,
|
||||
setting_properties):
|
||||
if context is not undefined:
|
||||
descr = context.cfgimpl_get_description()
|
||||
if descr._cache_consistencies is None:
|
||||
|
@ -586,10 +627,16 @@ class Option(OnlyOption):
|
|||
opts.append(opt._impl_to_dyn(name, path))
|
||||
else:
|
||||
opts = all_cons_opts
|
||||
err = opts[0]._launch_consistency(self, func, option, value,
|
||||
context, index, submulti_idx,
|
||||
opts, warnings_only,
|
||||
transitive)
|
||||
err = opts[0]()._launch_consistency(self,
|
||||
func,
|
||||
option,
|
||||
value,
|
||||
context,
|
||||
index,
|
||||
opts,
|
||||
warnings_only,
|
||||
transitive,
|
||||
setting_properties)
|
||||
if err:
|
||||
return err
|
||||
|
||||
|
@ -680,7 +727,10 @@ class Option(OnlyOption):
|
|||
|
||||
#____________________________________________________________
|
||||
# consistency
|
||||
def _add_consistency(self, func, all_cons_opts, params):
|
||||
def _add_consistency(self,
|
||||
func,
|
||||
all_cons_opts,
|
||||
params):
|
||||
cons = (func, all_cons_opts, params)
|
||||
consistencies = getattr(self, '_consistencies', None)
|
||||
if consistencies is None:
|
||||
|
|
|
@ -125,8 +125,8 @@ class CacheOptionDescription(BaseOption):
|
|||
'must be in same master/slaves for {1}').format(
|
||||
require_opt.impl_getname(), option.impl_getname()))
|
||||
else:
|
||||
raise ValueError(_('malformed requirements option {0} '
|
||||
'must not be a multi for {1}').format(
|
||||
raise ValueError(_('malformed requirements option "{0}" '
|
||||
'must not be a multi for "{1}"').format(
|
||||
require_opt.impl_getname(), option.impl_getname()))
|
||||
if init:
|
||||
if len(cache_option) != len(set(cache_option)):
|
||||
|
@ -137,7 +137,7 @@ class CacheOptionDescription(BaseOption):
|
|||
if _consistencies != {}:
|
||||
self._cache_consistencies = {}
|
||||
for opt, cons in _consistencies.items():
|
||||
if opt not in cache_option: # pragma: optional cover
|
||||
if opt() not in cache_option: # pragma: optional cover
|
||||
raise ConfigError(_('consistency with option {0} '
|
||||
'which is not in Config').format(
|
||||
opt.impl_getname()))
|
||||
|
@ -437,12 +437,12 @@ class OptionDescription(OptionDescriptionWalk):
|
|||
for child in valid_child:
|
||||
if child == old: # pragma: optional cover
|
||||
raise ConflictError(_('duplicate option name: '
|
||||
'{0}').format(child))
|
||||
'"{0}"').format(child))
|
||||
if dynopt_names:
|
||||
for dynopt in dynopt_names:
|
||||
if child != dynopt and child.startswith(dynopt):
|
||||
raise ConflictError(_('option must not start as '
|
||||
'dynoptiondescription'))
|
||||
raise ConflictError(_('the option\'s name "{}" start as '
|
||||
'the dynoptiondescription\'s name "{}"').format(child, dynopt))
|
||||
old = child
|
||||
_setattr = object.__setattr__
|
||||
_setattr(self, '_children', (tuple(child_names), tuple(children)))
|
||||
|
@ -623,7 +623,7 @@ class MasterSlaves(OptionDescription):
|
|||
name))
|
||||
slaves.append(child)
|
||||
child._add_dependency(self)
|
||||
for child in children:
|
||||
for idx, child in enumerate(children):
|
||||
if child._is_symlinkoption(): # pragma: optional cover
|
||||
raise ValueError(_("master group {0} shall not have "
|
||||
"a symlinkoption").format(self.impl_getname()))
|
||||
|
@ -635,6 +635,11 @@ class MasterSlaves(OptionDescription):
|
|||
"in group {1}"
|
||||
": this option is not a multi"
|
||||
"").format(child.impl_getname(), self.impl_getname()))
|
||||
# no empty property for save
|
||||
if idx != 0:
|
||||
properties = list(child._properties)
|
||||
properties.remove('empty')
|
||||
child._properties = tuple(properties)
|
||||
callback, callback_params = master.impl_get_callback()
|
||||
if callback is not None and callback_params != {}:
|
||||
for callbacks in callback_params.values():
|
||||
|
|
|
@ -106,7 +106,8 @@ rw_append = set(['frozen', 'disabled', 'validator', 'hidden'])
|
|||
rw_remove = set(['permissive', 'everything_frozen', 'mandatory', 'empty'])
|
||||
|
||||
|
||||
forbidden_set_properties = set(['force_store_value'])
|
||||
forbidden_set_properties = frozenset(['force_store_value'])
|
||||
forbidden_set_permissives = frozenset(['frozen', 'force_default_on_freeze'])
|
||||
|
||||
|
||||
log = getLogger('tiramisu')
|
||||
|
@ -124,15 +125,16 @@ class _NameSpace(object):
|
|||
when attribute is added, we cannot delete it
|
||||
"""
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name in self.__dict__: # pragma: optional cover
|
||||
def __setattr__(self,
|
||||
name,
|
||||
value):
|
||||
if name in self.__dict__:
|
||||
raise ConstError(_("can't rebind {0}").format(name))
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __delattr__(self, name): # pragma: optional cover
|
||||
if name in self.__dict__:
|
||||
raise ConstError(_("can't unbind {0}").format(name))
|
||||
raise ValueError(name)
|
||||
def __delattr__(self,
|
||||
name):
|
||||
raise ConstError(_("can't unbind {0}").format(name))
|
||||
|
||||
|
||||
class GroupModule(_NameSpace):
|
||||
|
@ -168,69 +170,44 @@ class OwnerModule(_NameSpace):
|
|||
"""groups that are default (typically 'default')"""
|
||||
pass
|
||||
|
||||
|
||||
class MultiTypeModule(_NameSpace):
|
||||
"namespace for the master/slaves"
|
||||
class MultiType(str):
|
||||
pass
|
||||
|
||||
class DefaultMultiType(MultiType):
|
||||
pass
|
||||
|
||||
class MasterMultiType(MultiType):
|
||||
pass
|
||||
|
||||
class SlaveMultiType(MultiType):
|
||||
pass
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
def populate_groups():
|
||||
"""populates the available groups in the appropriate namespaces
|
||||
|
||||
groups.default
|
||||
default group set when creating a new optiondescription
|
||||
|
||||
groups.master
|
||||
master group is a special optiondescription, all suboptions should be
|
||||
multi option and all values should have same length, to find master's
|
||||
option, the optiondescription's name should be same than de master's
|
||||
option
|
||||
|
||||
groups.family
|
||||
example of group, no special behavior with this group's type
|
||||
"""
|
||||
groups.default = groups.DefaultGroupType('default')
|
||||
groups.master = groups.MasterGroupType('master')
|
||||
groups.family = groups.GroupType('family')
|
||||
|
||||
|
||||
def populate_owners():
|
||||
"""populates the available owners in the appropriate namespaces
|
||||
|
||||
default
|
||||
is the config owner after init time
|
||||
|
||||
user
|
||||
is the generic is the generic owner
|
||||
"""
|
||||
setattr(owners, 'default', owners.DefaultOwner('default'))
|
||||
setattr(owners, 'user', owners.Owner('user'))
|
||||
setattr(owners, 'forced', owners.Owner('forced'))
|
||||
|
||||
def addowner(name):
|
||||
def addowner(self, name):
|
||||
"""
|
||||
:param name: the name of the new owner
|
||||
"""
|
||||
setattr(owners, name, owners.Owner(name))
|
||||
setattr(owners, 'addowner', addowner)
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
# populate groups and owners with default attributes
|
||||
# populate groups
|
||||
groups = GroupModule()
|
||||
populate_groups()
|
||||
"""groups.default
|
||||
default group set when creating a new optiondescription"""
|
||||
groups.default = groups.DefaultGroupType('default')
|
||||
|
||||
"""groups.master
|
||||
master group is a special optiondescription, all suboptions should be
|
||||
multi option and all values should have same length, to find master's
|
||||
option, the optiondescription's name should be same than de master's
|
||||
option"""
|
||||
groups.master = groups.MasterGroupType('master')
|
||||
|
||||
""" groups.family
|
||||
example of group, no special behavior with this group's type"""
|
||||
groups.family = groups.GroupType('family')
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
# populate owners with default attributes
|
||||
owners = OwnerModule()
|
||||
populate_owners()
|
||||
"""default
|
||||
is the config owner after init time"""
|
||||
owners.default = owners.DefaultOwner('default')
|
||||
"""user
|
||||
is the generic is the generic owner"""
|
||||
owners.user = owners.Owner('user')
|
||||
"""forced
|
||||
special owner when value is forced"""
|
||||
owners.forced = owners.Owner('forced')
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
|
@ -241,73 +218,6 @@ class Undefined(object):
|
|||
undefined = Undefined()
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Property(object):
|
||||
"a property is responsible of the option's value access rules"
|
||||
__slots__ = ('_setting', '_properties', '_opt', '_path')
|
||||
|
||||
def __init__(self, setting, prop, opt=None, path=None):
|
||||
self._opt = opt
|
||||
self._path = path
|
||||
self._setting = setting
|
||||
self._properties = prop
|
||||
|
||||
def append(self, propname):
|
||||
"""Appends a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
self._append(propname)
|
||||
|
||||
def _append(self, propname, save=True):
|
||||
if self._opt is not None and self._opt.impl_getrequires() is not None \
|
||||
and propname in getattr(self._opt, '_calc_properties', static_set): # pragma: optional cover
|
||||
raise ValueError(_('cannot append {0} property for option {1}: '
|
||||
'this property is calculated').format(
|
||||
propname, self._opt.impl_getname()))
|
||||
if propname in forbidden_set_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(propname))
|
||||
self._properties.add(propname)
|
||||
if save:
|
||||
self._setting.setproperties(self._properties, self._opt, self._path, force=True)
|
||||
|
||||
def remove(self, propname):
|
||||
"""Removes a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
if propname in self._properties:
|
||||
self._properties.remove(propname)
|
||||
self._setting.setproperties(self._properties, self._opt, self._path)
|
||||
|
||||
def extend(self, propnames):
|
||||
"""Extends properties to the existing properties
|
||||
|
||||
:param propnames: an iterable made of property names
|
||||
:type propnames: iterable of string
|
||||
"""
|
||||
for propname in propnames:
|
||||
self._append(propname, save=False)
|
||||
self._setting.setproperties(self._properties, self._opt, self._path)
|
||||
|
||||
def reset(self):
|
||||
"""resets the properties (does not **clear** the properties,
|
||||
default properties are still present)
|
||||
"""
|
||||
self._setting.reset(_path=self._path)
|
||||
|
||||
def __contains__(self, propname):
|
||||
return propname in self._properties
|
||||
|
||||
def __repr__(self):
|
||||
return str(list(self._properties))
|
||||
|
||||
def get(self):
|
||||
return tuple(self._properties)
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
class Settings(object):
|
||||
"``config.Config()``'s configuration options settings"
|
||||
|
@ -341,321 +251,89 @@ class Settings(object):
|
|||
return context
|
||||
|
||||
#____________________________________________________________
|
||||
# properties methods
|
||||
def __contains__(self, propname):
|
||||
"enables the pythonic 'in' syntaxic sugar"
|
||||
return propname in self._getproperties(read_write=False)
|
||||
# get properties and permissive methods
|
||||
|
||||
def __repr__(self):
|
||||
return str(list(self._getproperties(read_write=False)))
|
||||
|
||||
def __getitem__(self, opt):
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self.getproperties(opt, path)
|
||||
def get_context_properties(self):
|
||||
ntime = int(time())
|
||||
if self._p_.hascache(None,
|
||||
None):
|
||||
is_cached, props = self._p_.getcache(None,
|
||||
ntime,
|
||||
None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached or 'cache' not in props:
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if meta is None:
|
||||
props = self._p_.getproperties(None,
|
||||
default_properties)
|
||||
else:
|
||||
props = meta.cfgimpl_get_settings().get_context_properties()
|
||||
if 'cache' in props:
|
||||
if 'expire' in props:
|
||||
ntime = ntime + expires_time
|
||||
else:
|
||||
ntime = None
|
||||
self._p_.setcache(None, props, ntime, None)
|
||||
return props
|
||||
|
||||
def getproperties(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties=undefined,
|
||||
setting_properties,
|
||||
index=None,
|
||||
obj=True):
|
||||
"""get properties for a specified option
|
||||
"""
|
||||
properties = self._getproperties(opt,
|
||||
path,
|
||||
index=index,
|
||||
setting_properties=setting_properties)
|
||||
if obj:
|
||||
return Property(self, properties, opt, path)
|
||||
return properties
|
||||
|
||||
def get_context_properties(self):
|
||||
return self._getproperties()
|
||||
|
||||
def __setitem__(self, opt, value): # pragma: optional cover
|
||||
raise ValueError(_('you should only append/remove properties'))
|
||||
|
||||
def reset(self, opt=None, _path=None, all_properties=False):
|
||||
if all_properties and (_path or opt): # pragma: optional cover
|
||||
raise ValueError(_('opt and all_properties must not be set '
|
||||
'together in reset'))
|
||||
if all_properties:
|
||||
self._p_.reset_all_properties()
|
||||
else:
|
||||
if opt is not None and _path is None:
|
||||
_path = opt.impl_getpath(self._getcontext())
|
||||
self._p_.delproperties(_path)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values'))
|
||||
|
||||
def _getproperties(self,
|
||||
opt=None,
|
||||
path=None,
|
||||
setting_properties=undefined,
|
||||
read_write=True,
|
||||
apply_requires=True,
|
||||
index=None):
|
||||
apply_requires=True):
|
||||
"""
|
||||
"""
|
||||
if opt is None:
|
||||
ntime = int(time())
|
||||
if self._p_.hascache(path, index):
|
||||
is_cached, props = self._p_.getcache(path, ntime, None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached or 'cache' not in props:
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if meta is None:
|
||||
props = self._p_.getproperties(path, default_properties)
|
||||
else:
|
||||
props = meta.cfgimpl_get_settings()._getproperties()
|
||||
if 'cache' in props:
|
||||
if 'expire' in props:
|
||||
ntime = ntime + expires_time
|
||||
else:
|
||||
ntime = None
|
||||
self._p_.setcache(path, props, ntime, None)
|
||||
else:
|
||||
if path is None: # pragma: optional cover
|
||||
raise ValueError(_('if opt is not None, path should not be'
|
||||
' None in _getproperties'))
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
is_cached = False
|
||||
is_cached = False
|
||||
|
||||
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, index):
|
||||
is_cached, props = self._p_.getcache(path, ntime, index)
|
||||
if not is_cached:
|
||||
props = self._p_.getproperties(path, opt.impl_getproperties())
|
||||
if not opt.impl_is_optiondescription() and opt.impl_is_multi() and \
|
||||
not opt.impl_is_master_slaves('slave'):
|
||||
props.add('empty')
|
||||
if apply_requires:
|
||||
requires = self.apply_requires(opt, path, setting_properties, index, False)
|
||||
if requires != set([]):
|
||||
props = copy(props)
|
||||
props |= requires
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, props, ntime, index)
|
||||
if read_write:
|
||||
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)
|
||||
if propname not in props:
|
||||
props.add(propname)
|
||||
self.setproperties(props, None, None)
|
||||
|
||||
def remove(self, propname):
|
||||
"deletes property propname in the Config's properties attribute"
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
if propname in props:
|
||||
props.remove(propname)
|
||||
self.setproperties(props, None, None)
|
||||
|
||||
def extend(self, propnames):
|
||||
for propname in propnames:
|
||||
self.append(propname)
|
||||
|
||||
def _setproperties(self, properties, opt, path, force=False):
|
||||
"""just for compatibility
|
||||
"""
|
||||
self.setproperties(properties, opt, path, force)
|
||||
|
||||
def setproperties(self, properties, opt, path, force=False):
|
||||
"""save properties for specified path
|
||||
(never save properties if same has option properties)
|
||||
"""
|
||||
if self._getcontext().cfgimpl_get_meta() is not None:
|
||||
raise ConfigError(_('cannot change global property with metaconfig'))
|
||||
if not force:
|
||||
forbidden_properties = forbidden_set_properties & properties
|
||||
if forbidden_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(
|
||||
' '.join(forbidden_properties)))
|
||||
self._p_.setproperties(path, properties)
|
||||
#values too because of slave values could have a PropertiesOptionError has value
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties',))
|
||||
|
||||
def getpermissive(self, setting_properties, path=None):
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
if 'cache' in setting_properties and self._pp_.hascache(path, None):
|
||||
is_cached, perm = self._pp_.getcache(path, ntime, None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached:
|
||||
if path is not None:
|
||||
perm = self._pp_.getpermissive(path)
|
||||
else:
|
||||
perm = self._pp_.getpermissive()
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._pp_.setcache(path, perm, ntime, None)
|
||||
return perm
|
||||
|
||||
#____________________________________________________________
|
||||
def validate_properties(self, opt_or_descr, is_descr, check_frozen, path,
|
||||
value=None, force_permissive=False,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None, debug=False):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
||||
:param check_frozen: in the validation process, an option is to be modified,
|
||||
the behavior can be different
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt 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,
|
||||
index=index)
|
||||
# calc properties
|
||||
properties &= setting_properties
|
||||
if not is_descr:
|
||||
#mandatory
|
||||
if 'mandatory' in properties and \
|
||||
not self._getcontext().cfgimpl_get_values()._isempty(
|
||||
opt_or_descr, value, index=index):
|
||||
properties.remove('mandatory')
|
||||
elif 'empty' in properties and \
|
||||
'empty' in setting_properties and \
|
||||
self._getcontext().cfgimpl_get_values()._isempty(
|
||||
opt_or_descr, value, force_allow_empty_list=True, index=index):
|
||||
properties.add('mandatory')
|
||||
# should return 'frozen' only when tried to modify a value
|
||||
if check_frozen and 'everything_frozen' in setting_properties:
|
||||
properties.add('frozen')
|
||||
elif 'frozen' in properties and not check_frozen:
|
||||
properties.remove('frozen')
|
||||
if 'empty' in properties:
|
||||
properties.remove('empty')
|
||||
|
||||
# remove permissive properties
|
||||
if properties != frozenset():
|
||||
# remove opt permissive
|
||||
# permissive affect option's permission with or without permissive
|
||||
# global property
|
||||
properties -= self.getpermissive(setting_properties, path)
|
||||
# remove global permissive if need
|
||||
if force_permissive is True or 'permissive' in setting_properties:
|
||||
properties -= self.getpermissive(setting_properties)
|
||||
|
||||
# at this point an option should not remain in properties
|
||||
if properties != frozenset():
|
||||
props = list(properties)
|
||||
datas = {'opt': opt_or_descr, 'path': path, 'setting_properties': setting_properties,
|
||||
'index': index, 'debug': True}
|
||||
if is_descr:
|
||||
opt_type = 'optiondescription'
|
||||
else:
|
||||
opt_type = 'option'
|
||||
if 'frozen' in properties:
|
||||
raise PropertiesOptionError(_('cannot change the value for '
|
||||
'option "{0}" this option is'
|
||||
' frozen').format(
|
||||
opt_or_descr.impl_getname()),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
else:
|
||||
if len(props) == 1:
|
||||
prop_msg = _('property')
|
||||
else:
|
||||
prop_msg = _('properties')
|
||||
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
|
||||
'because has {2} {3}'
|
||||
'').format(opt_type,
|
||||
opt_or_descr.impl_get_display_name(),
|
||||
prop_msg,
|
||||
display_list(props)),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
|
||||
def setpermissive(self, permissive, opt=None, path=None):
|
||||
"""
|
||||
enables us to put the permissives in the storage
|
||||
|
||||
:param path: the option's path
|
||||
:param type: str
|
||||
:param opt: if an option object is set, the path is extracted.
|
||||
it is better (faster) to set the path parameter
|
||||
instead of passing a :class:`tiramisu.option.Option()` object.
|
||||
"""
|
||||
if opt is not None and path is None:
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
if not isinstance(permissive, tuple): # pragma: optional cover
|
||||
raise TypeError(_('permissive must be a tuple'))
|
||||
self._pp_.setpermissive(path, permissive)
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=path, only=('properties', 'values'))
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = int(time()) + expires_time
|
||||
if apply_requires:
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
self._pp_.setcache(path, set(permissive), ntime, None)
|
||||
if 'cache' in setting_properties and self._p_.hascache(path,
|
||||
index):
|
||||
is_cached, props = self._p_.getcache(path,
|
||||
ntime,
|
||||
index)
|
||||
if not is_cached:
|
||||
props = self._p_.getproperties(path,
|
||||
opt.impl_getproperties())
|
||||
if apply_requires:
|
||||
requires = self.apply_requires(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index,
|
||||
False)
|
||||
#FIXME devrait etre un frozenset!
|
||||
if requires != set([]):
|
||||
props = copy(props)
|
||||
props |= requires
|
||||
|
||||
#____________________________________________________________
|
||||
def setowner(self, owner):
|
||||
":param owner: sets the default value for owner at the Config level"
|
||||
if not isinstance(owner, owners.Owner): # pragma: optional cover
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
self._owner = owner
|
||||
#FIXME qu'est ce qui se passe si pas de owner ??
|
||||
props -= self.getpermissive(path)
|
||||
if apply_requires and 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path,
|
||||
props,
|
||||
ntime,
|
||||
index)
|
||||
return props
|
||||
|
||||
def getowner(self):
|
||||
return self._owner
|
||||
def get_context_permissive(self):
|
||||
return self.getpermissive(None)
|
||||
|
||||
#____________________________________________________________
|
||||
def _read(self, remove, append):
|
||||
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, None)
|
||||
def getpermissive(self,
|
||||
path):
|
||||
return self._pp_.getpermissive(path)
|
||||
|
||||
def read_only(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(ro_remove, ro_append)
|
||||
|
||||
def read_write(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(rw_remove, rw_append)
|
||||
|
||||
def apply_requires(self, opt, path, setting_properties, index, debug):
|
||||
def apply_requires(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index,
|
||||
debug):
|
||||
"""carries out the jit (just in time) requirements between options
|
||||
|
||||
a requirement is a tuple of this form that comes from the option's
|
||||
|
@ -735,16 +413,16 @@ class Settings(object):
|
|||
idx = None
|
||||
try:
|
||||
value = context.getattr(reqpath,
|
||||
setting_properties,
|
||||
force_permissive=True,
|
||||
_setting_properties=setting_properties,
|
||||
index=idx)
|
||||
except PropertiesOptionError as err:
|
||||
if not transitive:
|
||||
if all_properties is None:
|
||||
all_properties = []
|
||||
for requires in opt.impl_getrequires():
|
||||
for require in requires:
|
||||
all_properties.append(require[1])
|
||||
for requires_ in opt.impl_getrequires():
|
||||
for require_ in requires_:
|
||||
all_properties.append(require_[1])
|
||||
if not set(err.proptype) - set(all_properties):
|
||||
continue
|
||||
properties = err.proptype
|
||||
|
@ -794,8 +472,228 @@ class Settings(object):
|
|||
break
|
||||
return calc_properties
|
||||
|
||||
#____________________________________________________________
|
||||
# set methods
|
||||
def set_context_properties(self, properties):
|
||||
self.setproperties(None, None, properties)
|
||||
|
||||
def setproperties(self,
|
||||
opt,
|
||||
path,
|
||||
properties):
|
||||
# force=False):
|
||||
"""save properties for specified path
|
||||
(never save properties if same has option properties)
|
||||
"""
|
||||
if self._getcontext().cfgimpl_get_meta() is not None:
|
||||
raise ConfigError(_('cannot change global property with metaconfig'))
|
||||
#if not force:
|
||||
forbidden_properties = forbidden_set_properties & properties
|
||||
if forbidden_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(
|
||||
' '.join(forbidden_properties)))
|
||||
if not isinstance(properties, frozenset):
|
||||
raise TypeError(_('properties must be a frozenset'))
|
||||
self._p_.setproperties(path,
|
||||
properties)
|
||||
#values too because of slave values could have a PropertiesOptionError has value
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path)
|
||||
|
||||
def set_context_permissive(self, permissive):
|
||||
self.setpermissive(None, None, permissive)
|
||||
|
||||
def setpermissive(self,
|
||||
opt,
|
||||
path,
|
||||
permissives):
|
||||
"""
|
||||
enables us to put the permissives in the storage
|
||||
|
||||
:param path: the option's path
|
||||
:param type: str
|
||||
:param opt: if an option object is set, the path is extracted.
|
||||
it is better (faster) to set the path parameter
|
||||
instead of passing a :class:`tiramisu.option.Option()` object.
|
||||
"""
|
||||
if not isinstance(permissives, frozenset):
|
||||
raise TypeError(_('permissive must be a frozenset'))
|
||||
forbidden_permissives = forbidden_set_permissives & permissives
|
||||
if forbidden_permissives:
|
||||
raise ConfigError(_('cannot add those permissives: {0}').format(
|
||||
' '.join(forbidden_permissives)))
|
||||
self._pp_.setpermissive(path, permissives)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path)
|
||||
|
||||
#____________________________________________________________
|
||||
# reset methods
|
||||
|
||||
def reset(self, opt=None, _path=None, all_properties=False):
|
||||
if all_properties and (_path or opt): # pragma: optional cover
|
||||
raise ValueError(_('opt and all_properties must not be set '
|
||||
'together in reset'))
|
||||
if all_properties:
|
||||
self._p_.reset_all_properties()
|
||||
else:
|
||||
if opt is not None and _path is None:
|
||||
_path = opt.impl_getpath(self._getcontext())
|
||||
self._p_.delproperties(_path)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=_path)
|
||||
|
||||
#____________________________________________________________
|
||||
# validate properties
|
||||
|
||||
def validate_properties(self,
|
||||
opt_or_descr,
|
||||
is_descr,
|
||||
check_frozen,
|
||||
path,
|
||||
value=None,
|
||||
force_permissive=False,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
debug=False):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
||||
:param check_frozen: in the validation process, an option is to be modified,
|
||||
the behavior can be different
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
if self_properties is not undefined:
|
||||
if not isinstance(self_properties, frozenset):
|
||||
raise Exception('pouet')
|
||||
properties = self_properties
|
||||
else:
|
||||
properties = self.getproperties(opt_or_descr,
|
||||
path,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
# calc properties
|
||||
properties &= setting_properties
|
||||
if not is_descr:
|
||||
#mandatory
|
||||
if 'mandatory' in properties and \
|
||||
not self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
|
||||
value,
|
||||
index=index):
|
||||
properties.remove('mandatory')
|
||||
elif 'empty' in properties and \
|
||||
'empty' in setting_properties and \
|
||||
self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
|
||||
value,
|
||||
force_allow_empty_list=True,
|
||||
index=index):
|
||||
properties.add('mandatory')
|
||||
# should return 'frozen' only when tried to modify a value
|
||||
if check_frozen and 'everything_frozen' in setting_properties:
|
||||
properties.add('frozen')
|
||||
elif 'frozen' in properties and not check_frozen:
|
||||
properties.remove('frozen')
|
||||
if 'empty' in properties:
|
||||
properties.remove('empty')
|
||||
|
||||
# remove permissive properties
|
||||
if properties != frozenset() and (force_permissive is True or
|
||||
'permissive' in setting_properties):
|
||||
# remove global permissive if need
|
||||
properties -= self.get_context_permissive()
|
||||
|
||||
# at this point an option should not remain in properties
|
||||
if properties != frozenset():
|
||||
props = list(properties)
|
||||
datas = {'opt': opt_or_descr,
|
||||
'path': path,
|
||||
'setting_properties': setting_properties,
|
||||
'index': index,
|
||||
'debug': True}
|
||||
if is_descr:
|
||||
opt_type = 'optiondescription'
|
||||
else:
|
||||
opt_type = 'option'
|
||||
if 'frozen' in properties:
|
||||
raise PropertiesOptionError(_('cannot change the value for '
|
||||
'option "{0}" this option is'
|
||||
' frozen').format(
|
||||
opt_or_descr.impl_getname()),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
else:
|
||||
if len(props) == 1:
|
||||
prop_msg = _('property')
|
||||
else:
|
||||
prop_msg = _('properties')
|
||||
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
|
||||
'because has {2} {3}'
|
||||
'').format(opt_type,
|
||||
opt_or_descr.impl_get_display_name(),
|
||||
prop_msg,
|
||||
display_list(props)),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
|
||||
#____________________________________________________________
|
||||
# read only/read write
|
||||
|
||||
def _read(self,
|
||||
remove,
|
||||
append):
|
||||
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.set_context_properties(frozenset(props))
|
||||
|
||||
def read_only(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(ro_remove,
|
||||
ro_append)
|
||||
|
||||
def read_write(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(rw_remove,
|
||||
rw_append)
|
||||
|
||||
#____________________________________________________________
|
||||
# get modified properties/permissives
|
||||
|
||||
def get_modified_properties(self):
|
||||
return self._p_.get_modified_properties()
|
||||
|
||||
def get_modified_permissives(self):
|
||||
return self._pp_.get_modified_permissives()
|
||||
|
||||
#____________________________________________________________
|
||||
# default owner methods
|
||||
|
||||
def setowner(self,
|
||||
owner):
|
||||
":param owner: sets the default value for owner at the Config level"
|
||||
if not isinstance(owner,
|
||||
owners.Owner): # pragma: optional cover
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
self._owner = owner
|
||||
|
||||
def getowner(self):
|
||||
return self._owner
|
||||
|
|
|
@ -34,7 +34,7 @@ class Properties(Cache):
|
|||
self._properties[path] = properties
|
||||
|
||||
def getproperties(self, path, default_properties):
|
||||
return self._properties.get(path, set(default_properties))
|
||||
return self._properties.get(path, frozenset(default_properties))
|
||||
|
||||
def reset_all_properties(self):
|
||||
self._properties.clear()
|
||||
|
|
|
@ -195,7 +195,11 @@ class Values(Cache):
|
|||
return 0
|
||||
return max(self._values[1][idx]) + 1
|
||||
|
||||
def getowner(self, path, default, index=None, only_default=False,
|
||||
def getowner(self,
|
||||
path,
|
||||
default,
|
||||
index=None,
|
||||
only_default=False,
|
||||
with_value=False):
|
||||
"""get owner for a path
|
||||
return: owner object
|
||||
|
@ -207,19 +211,28 @@ class Values(Cache):
|
|||
else:
|
||||
owner = default
|
||||
else:
|
||||
owner = self._getvalue(path, 3, index)
|
||||
owner = self._getvalue(path,
|
||||
3,
|
||||
index)
|
||||
if owner is undefined:
|
||||
owner = default
|
||||
else:
|
||||
owner = self._getvalue(path, 3, index)
|
||||
owner = self._getvalue(path,
|
||||
3,
|
||||
index)
|
||||
if owner is undefined:
|
||||
owner = default
|
||||
if with_value:
|
||||
return owner, self._getvalue(path, 2, index)
|
||||
return owner, self._getvalue(path,
|
||||
2,
|
||||
index)
|
||||
else:
|
||||
return owner
|
||||
|
||||
def _getvalue(self, path, nb, index):
|
||||
def _getvalue(self,
|
||||
path,
|
||||
nb,
|
||||
index):
|
||||
"""
|
||||
_values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2))
|
||||
"""
|
||||
|
|
|
@ -43,6 +43,9 @@ class Values(object):
|
|||
# the storage type is dictionary or sqlite3
|
||||
self._p_ = storage
|
||||
|
||||
#______________________________________________________________________
|
||||
# get context
|
||||
|
||||
def _getcontext(self):
|
||||
"""context could be None, we need to test it
|
||||
context is None only if all reference to `Config` object is deleted
|
||||
|
@ -54,6 +57,198 @@ class Values(object):
|
|||
raise ConfigError(_('the context does not exist anymore'))
|
||||
return context
|
||||
|
||||
#______________________________________________________________________
|
||||
# get value
|
||||
|
||||
def get_cached_value(self,
|
||||
opt,
|
||||
path=None,
|
||||
validate=True,
|
||||
force_permissive=False,
|
||||
trusted_cached_properties=True,
|
||||
validate_properties=True,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
check_frozen=False,
|
||||
display_warnings=True,
|
||||
_orig_context=undefined):
|
||||
context = self._getcontext()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
if path is None:
|
||||
path = opt.impl_getpath(context)
|
||||
ntime = None
|
||||
if self_properties is undefined:
|
||||
self_properties = settings.getproperties(opt,
|
||||
path,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
if 'cache' in setting_properties and self._p_.hascache(path, index) and \
|
||||
_orig_context is undefined:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
is_cached, value = self._p_.getcache(path,
|
||||
ntime,
|
||||
None)
|
||||
if index:
|
||||
value = value[index]
|
||||
if is_cached:
|
||||
if not trusted_cached_properties:
|
||||
# revalidate properties (because of not default properties)
|
||||
settings.validate_properties(opt,
|
||||
False,
|
||||
False,
|
||||
value=value,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties,
|
||||
index=index)
|
||||
return value
|
||||
if _orig_context is not undefined:
|
||||
_context = _orig_context
|
||||
else:
|
||||
_context = context
|
||||
val = self.get_validated_value(opt,
|
||||
path,
|
||||
validate,
|
||||
force_permissive,
|
||||
validate_properties,
|
||||
setting_properties,
|
||||
self_properties,
|
||||
index=index,
|
||||
check_frozen=check_frozen,
|
||||
display_warnings=display_warnings,
|
||||
_orig_context=_context)
|
||||
if index is None and 'cache' in setting_properties and \
|
||||
validate and validate_properties and force_permissive is False \
|
||||
and trusted_cached_properties is True and _orig_context is undefined:
|
||||
if 'expire' in setting_properties:
|
||||
if ntime is None:
|
||||
ntime = int(time())
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, val, ntime, None)
|
||||
return val
|
||||
|
||||
def get_validated_value(self,
|
||||
opt,
|
||||
path,
|
||||
validate,
|
||||
force_permissive,
|
||||
validate_properties,
|
||||
setting_properties,
|
||||
self_properties,
|
||||
index=None,
|
||||
check_frozen=False,
|
||||
display_warnings=True,
|
||||
_orig_context=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 []
|
||||
"""
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
config_error = None
|
||||
try:
|
||||
value = self.getvalue(opt,
|
||||
path,
|
||||
self_properties,
|
||||
index,
|
||||
validate,
|
||||
_orig_context)
|
||||
except ConfigError as value:
|
||||
value_error = True
|
||||
# For calculating properties, we need value (ie for mandatory
|
||||
# value).
|
||||
# If value is calculating with a PropertiesOptionError's option
|
||||
# getvalue raise a ConfigError.
|
||||
# We can not raise ConfigError if this option should raise
|
||||
# PropertiesOptionError too. So we get config_error and raise
|
||||
# ConfigError if properties did not raise.
|
||||
config_error = value
|
||||
# value is not set, for 'undefined' (cannot set None because of
|
||||
# mandatory property)
|
||||
value = undefined
|
||||
else:
|
||||
value_error = False
|
||||
if validate:
|
||||
err = opt.impl_validate(value,
|
||||
context,
|
||||
'validator' in setting_properties,
|
||||
force_index=index,
|
||||
display_error=True,
|
||||
display_warnings=False,
|
||||
setting_properties=setting_properties)
|
||||
if err:
|
||||
config_error = err
|
||||
value = None
|
||||
|
||||
if validate_properties:
|
||||
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,
|
||||
check_frozen,
|
||||
value=val_props,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties,
|
||||
index=index)
|
||||
if not value_error and validate and display_warnings:
|
||||
opt.impl_validate(value,
|
||||
context,
|
||||
'validator' in setting_properties,
|
||||
force_index=index,
|
||||
display_error=False,
|
||||
display_warnings=display_warnings,
|
||||
setting_properties=setting_properties)
|
||||
if config_error is not None:
|
||||
return config_error
|
||||
return value
|
||||
|
||||
def getvalue(self,
|
||||
opt,
|
||||
path,
|
||||
self_properties,
|
||||
index,
|
||||
validate,
|
||||
_orig_context):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
:returns: the option's value (or the default value if not set)
|
||||
"""
|
||||
force_default = 'frozen' in self_properties and \
|
||||
'force_default_on_freeze' in self_properties
|
||||
# not default value
|
||||
if index is None or not opt.impl_is_master_slaves('slave'):
|
||||
_index = None
|
||||
else:
|
||||
_index = index
|
||||
owner, value = self._p_.getowner(path,
|
||||
owners.default,
|
||||
only_default=True,
|
||||
index=_index,
|
||||
with_value=True)
|
||||
is_default = owner == owners.default
|
||||
if not is_default and not force_default:
|
||||
if index is not None and not opt.impl_is_master_slaves('slave'):
|
||||
if len(value) > index:
|
||||
return value[index]
|
||||
#value is smaller than expected
|
||||
#so return default value
|
||||
else:
|
||||
return value
|
||||
return self._getdefaultvalue(opt,
|
||||
path,
|
||||
index,
|
||||
validate,
|
||||
_orig_context)
|
||||
|
||||
def getdefaultvalue(self,
|
||||
opt,
|
||||
path,
|
||||
|
@ -84,8 +279,7 @@ class Values(object):
|
|||
def _reset_cache():
|
||||
# calculated value could be a new value, so reset cache
|
||||
_orig_context.cfgimpl_reset_cache(opt=opt,
|
||||
path=path,
|
||||
only=('values', 'properties'))
|
||||
path=path)
|
||||
|
||||
#FIXME with_meta should be calculated here...
|
||||
with_meta = True
|
||||
|
@ -170,60 +364,253 @@ class Values(object):
|
|||
value = opt.impl_getdefault_multi()
|
||||
return value
|
||||
|
||||
def _getvalue(self,
|
||||
opt,
|
||||
path,
|
||||
self_properties,
|
||||
index,
|
||||
validate,
|
||||
_orig_context):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
:returns: the option's value (or the default value if not set)
|
||||
"""
|
||||
force_default = 'frozen' in self_properties and \
|
||||
'force_default_on_freeze' in self_properties
|
||||
# not default value
|
||||
if index is None or not opt.impl_is_master_slaves('slave'):
|
||||
_index = None
|
||||
def isempty(self,
|
||||
opt,
|
||||
value,
|
||||
force_allow_empty_list=False,
|
||||
index=None):
|
||||
"convenience method to know if an option is empty"
|
||||
if value is undefined:
|
||||
return False
|
||||
else:
|
||||
_index = index
|
||||
owner, value = self._p_.getowner(path,
|
||||
owners.default,
|
||||
only_default=True,
|
||||
index=_index,
|
||||
with_value=True)
|
||||
is_default = owner == owners.default
|
||||
if not is_default and not force_default:
|
||||
if index is not None and not opt.impl_is_master_slaves('slave'):
|
||||
if len(value) > index:
|
||||
return value[index]
|
||||
#value is smaller than expected
|
||||
#so return default value
|
||||
empty = opt._empty
|
||||
if index in [None, undefined] and opt.impl_is_multi():
|
||||
if force_allow_empty_list:
|
||||
allow_empty_list = True
|
||||
else:
|
||||
allow_empty_list = opt.impl_allow_empty_list()
|
||||
if allow_empty_list is undefined:
|
||||
if opt.impl_is_master_slaves('slave'):
|
||||
allow_empty_list = True
|
||||
else:
|
||||
allow_empty_list = False
|
||||
isempty = value is None or (not allow_empty_list and value == []) or \
|
||||
None in value or empty in value
|
||||
else:
|
||||
return value
|
||||
return self._getdefaultvalue(opt,
|
||||
path,
|
||||
index,
|
||||
validate,
|
||||
_orig_context)
|
||||
isempty = value is None or value == empty
|
||||
return isempty
|
||||
|
||||
def get_modified_values(self):
|
||||
return self._p_.get_modified_values()
|
||||
|
||||
def __contains__(self, opt):
|
||||
"""
|
||||
implements the 'in' keyword syntax in order provide a pythonic way
|
||||
to kow if an option have a value
|
||||
#______________________________________________________________________
|
||||
# set value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
"""
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self._contains(path)
|
||||
def setvalue(self,
|
||||
opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
index,
|
||||
setting_properties,
|
||||
_commit):
|
||||
|
||||
def _contains(self, path):
|
||||
return self._p_.hasvalue(path)
|
||||
context = self._getcontext()
|
||||
owner = context.cfgimpl_get_settings().getowner()
|
||||
if 'validator' in setting_properties:
|
||||
if opt._has_consistencies():
|
||||
# set value to a fake config when option has dependency
|
||||
# validation will be complet in this case (consistency, ...)
|
||||
tested_context = context._gen_fake_values()
|
||||
tested_values = tested_context.cfgimpl_get_values()
|
||||
tested_values._setvalue(opt,
|
||||
path,
|
||||
value,
|
||||
index=index,
|
||||
owner=owner)
|
||||
else:
|
||||
tested_context = context
|
||||
tested_values = self
|
||||
tested_values.validate_setitem(opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
setting_properties,
|
||||
index)
|
||||
|
||||
self._setvalue(opt,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index=index,
|
||||
commit=_commit)
|
||||
|
||||
def validate_setitem(self,
|
||||
opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
setting_properties,
|
||||
index):
|
||||
|
||||
context = self._getcontext()
|
||||
# First validate properties with this value
|
||||
context.cfgimpl_get_settings().validate_properties(opt,
|
||||
False,
|
||||
True,
|
||||
value=value,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
# Value must be valid for option
|
||||
opt.impl_validate(value,
|
||||
context,
|
||||
display_warnings=False,
|
||||
force_index=index,
|
||||
setting_properties=setting_properties)
|
||||
# No error found so emit warnings
|
||||
opt.impl_validate(value,
|
||||
context,
|
||||
display_error=False,
|
||||
force_index=index,
|
||||
setting_properties=setting_properties)
|
||||
|
||||
def _setvalue(self,
|
||||
opt,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index=None,
|
||||
commit=True):
|
||||
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path)
|
||||
if isinstance(value, list):
|
||||
# copy
|
||||
value = list(value)
|
||||
self._p_.setvalue(path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit)
|
||||
|
||||
def _is_meta(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
force_permissive=False):
|
||||
context = self._getcontext()
|
||||
if context.cfgimpl_get_meta() is None:
|
||||
return False
|
||||
return self.is_default_owner(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
validate_meta=False,
|
||||
index=None,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
#______________________________________________________________________
|
||||
# owner
|
||||
|
||||
def getowner(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index=None,
|
||||
force_permissive=False):
|
||||
"""
|
||||
retrieves the option's owner
|
||||
|
||||
:param opt: the `option.Option` object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:returns: a `setting.owners.Owner` object
|
||||
"""
|
||||
if opt._is_symlinkoption() and \
|
||||
not isinstance(opt, DynSymLinkOption):
|
||||
opt = opt._impl_getopt()
|
||||
return self._getowner(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
def _getowner(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
force_permissive=False,
|
||||
validate_meta=undefined,
|
||||
self_properties=undefined,
|
||||
only_default=False,
|
||||
index=None):
|
||||
"""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 self_properties is undefined:
|
||||
self_properties = context.cfgimpl_get_settings().getproperties(opt,
|
||||
path,
|
||||
setting_properties)
|
||||
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
|
||||
return owners.default
|
||||
owner = self._p_.getowner(path,
|
||||
owners.default,
|
||||
only_default=only_default,
|
||||
index=index)
|
||||
if validate_meta is undefined:
|
||||
if opt.impl_is_master_slaves('slave'):
|
||||
master = opt.impl_get_master_slaves().getmaster(opt)
|
||||
masterp = master.impl_getpath(context)
|
||||
validate_meta = self._is_meta(master,
|
||||
masterp,
|
||||
setting_properties,
|
||||
force_permissive=force_permissive)
|
||||
else:
|
||||
validate_meta = True
|
||||
if validate_meta and owner is owners.default:
|
||||
meta = context.cfgimpl_get_meta()
|
||||
if meta is not None:
|
||||
owner = meta.cfgimpl_get_values()._getowner(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
force_permissive=force_permissive,
|
||||
self_properties=self_properties,
|
||||
only_default=only_default,
|
||||
index=index)
|
||||
return owner
|
||||
|
||||
def setowner(self,
|
||||
path,
|
||||
owner,
|
||||
index=None):
|
||||
"""
|
||||
sets a owner to an option
|
||||
|
||||
:param opt: the `option.Option` object
|
||||
:param owner: a valid owner, that is a `setting.owners.Owner` object
|
||||
"""
|
||||
if not isinstance(owner, owners.Owner):
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
|
||||
if not self._p_.hasvalue(path):
|
||||
raise ConfigError(_('no value for {0} cannot change owner to {1}'
|
||||
'').format(path, owner))
|
||||
self._p_.setowner(path, owner, index=index)
|
||||
|
||||
def is_default_owner(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
validate_meta=True,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
force_permissive=False):
|
||||
owner = self._getowner(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
validate_meta=validate_meta,
|
||||
self_properties=self_properties,
|
||||
only_default=True,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
return owner == owners.default
|
||||
|
||||
#______________________________________________________________________
|
||||
# reset
|
||||
|
||||
def reset(self,
|
||||
opt,
|
||||
|
@ -235,7 +622,7 @@ class Values(object):
|
|||
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
hasvalue = self._contains(path)
|
||||
hasvalue = self._p_.hasvalue(path)
|
||||
|
||||
if validate and hasvalue and 'validator' in setting_properties:
|
||||
fake_context = context._gen_fake_values()
|
||||
|
@ -258,19 +645,15 @@ class Values(object):
|
|||
_commit=_commit,
|
||||
force_permissive=force_permissive)
|
||||
if hasvalue:
|
||||
if 'force_store_value' in setting._getproperties(opt=opt,
|
||||
path=path,
|
||||
setting_properties=setting_properties,
|
||||
read_write=False,
|
||||
apply_requires=False):
|
||||
if 'force_store_value' in setting.getproperties(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
apply_requires=False):
|
||||
value = self._getdefaultvalue(opt,
|
||||
path,
|
||||
True,
|
||||
undefined,
|
||||
None,
|
||||
validate,
|
||||
context)
|
||||
if isinstance(value, Exception): # pragma: no cover
|
||||
raise value
|
||||
self._setvalue(opt,
|
||||
path,
|
||||
value,
|
||||
|
@ -281,8 +664,7 @@ class Values(object):
|
|||
self._p_.resetvalue(path,
|
||||
_commit)
|
||||
context.cfgimpl_reset_cache(opt=opt,
|
||||
path=path,
|
||||
only=('values', 'properties'))
|
||||
path=path)
|
||||
|
||||
def reset_slave(self,
|
||||
opt,
|
||||
|
@ -301,14 +683,12 @@ class Values(object):
|
|||
index,
|
||||
setting_properties,
|
||||
validate=False)
|
||||
ret = fake_value.get_cached_value(opt,
|
||||
path,
|
||||
index=index,
|
||||
setting_properties=setting_properties,
|
||||
check_frozen=True,
|
||||
force_permissive=force_permissive)
|
||||
if isinstance(ret, Exception):
|
||||
raise ret
|
||||
fake_value.get_cached_value(opt,
|
||||
path,
|
||||
index=index,
|
||||
setting_properties=setting_properties,
|
||||
check_frozen=True,
|
||||
force_permissive=force_permissive)
|
||||
self._p_.resetvalue_index(path, index)
|
||||
|
||||
def reset_master(self,
|
||||
|
@ -325,457 +705,21 @@ class Values(object):
|
|||
check_frozen=True,
|
||||
force_permissive=force_permissive)
|
||||
current_value.pop(index)
|
||||
ret = self.setitem(opt,
|
||||
current_value,
|
||||
path,
|
||||
force_permissive=force_permissive,
|
||||
not_raises=True,
|
||||
index=None,
|
||||
setting_properties=setting_properties,
|
||||
_commit=True)
|
||||
if ret:
|
||||
return ret
|
||||
self.setvalue(opt,
|
||||
current_value,
|
||||
path,
|
||||
force_permissive=force_permissive,
|
||||
index=None,
|
||||
setting_properties=setting_properties,
|
||||
_commit=True)
|
||||
subconfig.cfgimpl_get_description().pop(opt,
|
||||
path,
|
||||
self,
|
||||
index)
|
||||
|
||||
def _isempty(self,
|
||||
opt,
|
||||
value,
|
||||
force_allow_empty_list=False,
|
||||
index=None):
|
||||
"convenience method to know if an option is empty"
|
||||
if value is undefined:
|
||||
return False
|
||||
else:
|
||||
empty = opt._empty
|
||||
if index in [None, undefined] and opt.impl_is_multi():
|
||||
if force_allow_empty_list:
|
||||
allow_empty_list = True
|
||||
else:
|
||||
allow_empty_list = opt.impl_allow_empty_list()
|
||||
if allow_empty_list is undefined:
|
||||
if opt.impl_is_master_slaves('slave'):
|
||||
allow_empty_list = True
|
||||
else:
|
||||
allow_empty_list = False
|
||||
isempty = value is None or (not allow_empty_list and value == []) or \
|
||||
None in value or empty in value
|
||||
else:
|
||||
isempty = value is None or value == empty
|
||||
return isempty
|
||||
|
||||
def __getitem__(self, opt):
|
||||
"enables us to use the pythonic dictionary-like access to values"
|
||||
return self.get_cached_value(opt)
|
||||
|
||||
def get_cached_value(self,
|
||||
opt,
|
||||
path=None,
|
||||
validate=True,
|
||||
force_permissive=False,
|
||||
trusted_cached_properties=True,
|
||||
validate_properties=True,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
check_frozen=False,
|
||||
display_warnings=True,
|
||||
_orig_context=undefined):
|
||||
context = self._getcontext()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
if path is None:
|
||||
path = opt.impl_getpath(context)
|
||||
ntime = None
|
||||
if setting_properties is undefined:
|
||||
setting_properties = settings._getproperties(read_write=False)
|
||||
if self_properties is undefined:
|
||||
self_properties = settings._getproperties(opt,
|
||||
path,
|
||||
read_write=False,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
if 'cache' in setting_properties and self._p_.hascache(path, index) and \
|
||||
_orig_context is undefined:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
is_cached, value = self._p_.getcache(path, ntime, None)
|
||||
if index:
|
||||
value = value[index]
|
||||
if is_cached:
|
||||
#if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
|
||||
# value = Multi(value, self.context, opt, path)
|
||||
if not trusted_cached_properties:
|
||||
# revalidate properties (because of not default properties)
|
||||
props = settings.validate_properties(opt,
|
||||
False,
|
||||
False,
|
||||
value=value,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties,
|
||||
index=index)
|
||||
if props:
|
||||
return props
|
||||
return value
|
||||
#if not from_masterslave and opt.impl_is_master_slaves():
|
||||
# val = opt.impl_get_master_slaves().getitem(self, opt, path,
|
||||
# validate,
|
||||
# force_permissive,
|
||||
# trusted_cached_properties,
|
||||
# validate_properties,
|
||||
# setting_properties=setting_properties,
|
||||
# index=index,
|
||||
# self_properties=self_properties,
|
||||
# check_frozen=check_frozen)
|
||||
#else:
|
||||
if _orig_context is not undefined:
|
||||
_context = _orig_context
|
||||
else:
|
||||
_context = context
|
||||
val = self._get_validated_value(opt,
|
||||
path,
|
||||
validate,
|
||||
force_permissive,
|
||||
validate_properties,
|
||||
setting_properties,
|
||||
self_properties,
|
||||
index=index,
|
||||
check_frozen=check_frozen,
|
||||
display_warnings=display_warnings,
|
||||
_orig_context=_context)
|
||||
if isinstance(val, Exception):
|
||||
return val
|
||||
if index is None and 'cache' in setting_properties and \
|
||||
validate and validate_properties and force_permissive is False \
|
||||
and trusted_cached_properties is True and _orig_context is undefined:
|
||||
if 'expire' in setting_properties:
|
||||
if ntime is None:
|
||||
ntime = int(time())
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, val, ntime, None)
|
||||
return val
|
||||
|
||||
def _get_validated_value(self,
|
||||
opt,
|
||||
path,
|
||||
validate,
|
||||
force_permissive,
|
||||
validate_properties,
|
||||
setting_properties,
|
||||
self_properties,
|
||||
index=None,
|
||||
check_frozen=False,
|
||||
display_warnings=True,
|
||||
_orig_context=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 []
|
||||
"""
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
config_error = None
|
||||
try:
|
||||
value = self._getvalue(opt,
|
||||
path,
|
||||
self_properties,
|
||||
index,
|
||||
validate,
|
||||
_orig_context)
|
||||
except ConfigError as value:
|
||||
value_error = True
|
||||
# For calculating properties, we need value (ie for mandatory
|
||||
# value).
|
||||
# If value is calculating with a PropertiesOptionError's option
|
||||
# _getvalue raise a ConfigError.
|
||||
# We can not raise ConfigError if this option should raise
|
||||
# PropertiesOptionError too. So we get config_error and raise
|
||||
# ConfigError if properties did not raise.
|
||||
config_error = value
|
||||
# value is not set, for 'undefined' (cannot set None because of
|
||||
# mandatory property)
|
||||
value = undefined
|
||||
else:
|
||||
value_error = False
|
||||
if validate:
|
||||
err = opt.impl_validate(value,
|
||||
context,
|
||||
'validator' in setting_properties,
|
||||
force_index=index,
|
||||
display_error=True,
|
||||
display_warnings=False,
|
||||
setting_properties=setting_properties)
|
||||
if err:
|
||||
config_error = err
|
||||
value = None
|
||||
|
||||
if validate_properties:
|
||||
if config_error is not None:
|
||||
# should not raise PropertiesOptionError if option is
|
||||
# mandatory
|
||||
val_props = undefined
|
||||
else:
|
||||
val_props = value
|
||||
props = setting.validate_properties(opt,
|
||||
False,
|
||||
check_frozen,
|
||||
value=val_props,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
self_properties=self_properties,
|
||||
index=index)
|
||||
if props:
|
||||
return props
|
||||
if not value_error and validate and display_warnings:
|
||||
opt.impl_validate(value,
|
||||
context,
|
||||
'validator' in setting_properties,
|
||||
force_index=index,
|
||||
display_error=False,
|
||||
display_warnings=display_warnings,
|
||||
setting_properties=setting_properties)
|
||||
if config_error is not None:
|
||||
return config_error
|
||||
return value
|
||||
|
||||
def setitem(self,
|
||||
opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
not_raises,
|
||||
index,
|
||||
setting_properties,
|
||||
_commit):
|
||||
|
||||
context = self._getcontext()
|
||||
owner = context.cfgimpl_get_settings().getowner()
|
||||
if 'validator' in setting_properties:
|
||||
if opt._has_consistencies():
|
||||
# set value to a fake config when option has dependency
|
||||
# validation will be complet in this case (consistency, ...)
|
||||
tested_context = context._gen_fake_values()
|
||||
tested_values = tested_context.cfgimpl_get_values()
|
||||
tested_values._setvalue(opt,
|
||||
path,
|
||||
value,
|
||||
index=index,
|
||||
owner=owner)
|
||||
else:
|
||||
tested_context = context
|
||||
tested_values = self
|
||||
props = tested_values.validate_setitem(opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
setting_properties,
|
||||
index)
|
||||
if props:
|
||||
if not not_raises:
|
||||
raise props
|
||||
return props
|
||||
|
||||
self._setvalue(opt,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index=index,
|
||||
commit=_commit)
|
||||
|
||||
def validate_setitem(self,
|
||||
opt,
|
||||
value,
|
||||
path,
|
||||
force_permissive,
|
||||
setting_properties,
|
||||
index):
|
||||
|
||||
context = self._getcontext()
|
||||
# First validate properties with this value
|
||||
props = context.cfgimpl_get_settings().validate_properties(opt,
|
||||
False,
|
||||
True,
|
||||
value=value,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
if props:
|
||||
return props
|
||||
# Value must be valid for option
|
||||
err = opt.impl_validate(value,
|
||||
context,
|
||||
display_warnings=False,
|
||||
force_index=index,
|
||||
setting_properties=setting_properties)
|
||||
if err:
|
||||
return err
|
||||
# No error found so emit warnings
|
||||
opt.impl_validate(value,
|
||||
context,
|
||||
display_error=False,
|
||||
force_index=index,
|
||||
setting_properties=setting_properties)
|
||||
|
||||
def _setvalue(self,
|
||||
opt,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index=None,
|
||||
commit=True):
|
||||
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path,
|
||||
only=('values', 'properties'))
|
||||
if isinstance(value, list):
|
||||
# copy
|
||||
value = list(value)
|
||||
self._p_.setvalue(path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit)
|
||||
|
||||
def _is_meta(self, opt, path, force_permissive=False):
|
||||
context = self._getcontext()
|
||||
if context.cfgimpl_get_meta() is None:
|
||||
return False
|
||||
setting = context.cfgimpl_get_settings()
|
||||
self_properties = setting._getproperties(opt, path, read_write=False)
|
||||
return self.is_default_owner(opt, path=path, validate_properties=True,
|
||||
validate_meta=False, index=None,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
def getowner(self, opt, index=None, force_permissive=False):
|
||||
"""
|
||||
retrieves the option's owner
|
||||
|
||||
:param opt: the `option.Option` object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:returns: a `setting.owners.Owner` object
|
||||
"""
|
||||
if opt._is_symlinkoption() and \
|
||||
not isinstance(opt, DynSymLinkOption):
|
||||
opt = opt._impl_getopt()
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self._getowner(opt,
|
||||
path,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
def _getowner(self,
|
||||
opt,
|
||||
path,
|
||||
validate_properties=True,
|
||||
force_permissive=False,
|
||||
validate_meta=undefined,
|
||||
self_properties=undefined,
|
||||
only_default=False,
|
||||
index=None):
|
||||
"""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 self_properties is undefined:
|
||||
self_properties = context.cfgimpl_get_settings()._getproperties(
|
||||
opt, path, read_write=False)
|
||||
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
|
||||
return owners.default
|
||||
if validate_properties:
|
||||
value = self.get_cached_value(opt,
|
||||
path=path,
|
||||
force_permissive=force_permissive,
|
||||
self_properties=self_properties,
|
||||
index=index)
|
||||
if isinstance(value, Exception):
|
||||
raise value
|
||||
|
||||
owner = self._p_.getowner(path, owners.default, only_default=only_default, index=index)
|
||||
if validate_meta is undefined:
|
||||
if opt.impl_is_master_slaves('slave'):
|
||||
master = opt.impl_get_master_slaves().getmaster(opt)
|
||||
masterp = master.impl_getpath(context)
|
||||
validate_meta = self._is_meta(master, masterp)
|
||||
else:
|
||||
validate_meta = True
|
||||
if validate_meta and owner is owners.default:
|
||||
meta = context.cfgimpl_get_meta()
|
||||
if meta is not None:
|
||||
owner = meta.cfgimpl_get_values()._getowner(opt,
|
||||
path,
|
||||
validate_properties=validate_properties,
|
||||
force_permissive=force_permissive,
|
||||
self_properties=self_properties,
|
||||
only_default=only_default,
|
||||
index=index)
|
||||
return owner
|
||||
|
||||
def setowner(self, opt, owner, index=None, force_permissive=False):
|
||||
"""
|
||||
sets a owner to an option
|
||||
|
||||
:param opt: the `option.Option` object
|
||||
:param owner: a valid owner, that is a `setting.owners.Owner` object
|
||||
"""
|
||||
if not isinstance(owner, owners.Owner):
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
|
||||
False,
|
||||
True,
|
||||
path,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
if props:
|
||||
raise props
|
||||
if not self._p_.hasvalue(path):
|
||||
raise ConfigError(_('no value for {0} cannot change owner to {1}'
|
||||
'').format(path, owner))
|
||||
self._p_.setowner(path, owner, index=index)
|
||||
|
||||
def is_default_owner(self, opt, path=None, validate_properties=True,
|
||||
validate_meta=True, index=None,
|
||||
force_permissive=False):
|
||||
"""
|
||||
:param config: *must* be only the **parent** config
|
||||
(not the toplevel config)
|
||||
:return: boolean
|
||||
"""
|
||||
if path is None:
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self._is_default_owner(opt,
|
||||
path,
|
||||
validate_properties=validate_properties,
|
||||
validate_meta=validate_meta,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
def _is_default_owner(self,
|
||||
opt,
|
||||
path,
|
||||
validate_properties=True,
|
||||
validate_meta=True,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
force_permissive=False):
|
||||
owner = self._getowner(opt,
|
||||
path,
|
||||
validate_properties=validate_properties,
|
||||
validate_meta=validate_meta,
|
||||
self_properties=self_properties,
|
||||
only_default=True,
|
||||
index=index,
|
||||
force_permissive=force_permissive)
|
||||
return owner == owners.default
|
||||
|
||||
#______________________________________________________________________
|
||||
# information
|
||||
|
||||
def set_information(self, key, value):
|
||||
"""updates the information's attribute
|
||||
|
||||
|
@ -794,6 +738,9 @@ class Values(object):
|
|||
def del_information(self, key, raises=True):
|
||||
self._p_.del_information(key, raises)
|
||||
|
||||
#______________________________________________________________________
|
||||
# mandatory warnings
|
||||
|
||||
def mandatory_warnings(self, force_permissive=True):
|
||||
"""convenience function to trace Options that are mandatory and
|
||||
where no value has been set
|
||||
|
@ -802,7 +749,7 @@ class Values(object):
|
|||
"""
|
||||
context = self._getcontext()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
setting_properties = context.cfgimpl_get_settings()._getproperties()
|
||||
setting_properties = context.cfgimpl_get_settings().get_context_properties()
|
||||
setting_properties.update(['mandatory', 'empty'])
|
||||
def _is_properties_option(err, path):
|
||||
#FIXME hum ...
|
||||
|
@ -834,9 +781,9 @@ class Values(object):
|
|||
if opt._is_symlinkoption() and \
|
||||
not isinstance(opt, DynSymLinkOption):
|
||||
continue
|
||||
self_properties = settings._getproperties(opt, path,
|
||||
read_write=False,
|
||||
setting_properties=setting_properties)
|
||||
self_properties = settings.getproperties(opt,
|
||||
path,
|
||||
setting_properties=setting_properties)
|
||||
if 'mandatory' in self_properties or 'empty' in self_properties:
|
||||
err = self.get_cached_value(opt, path=path,
|
||||
trusted_cached_properties=False,
|
||||
|
@ -859,18 +806,3 @@ class Values(object):
|
|||
descr = context.cfgimpl_get_description()
|
||||
for path in _mandatory_warnings(descr):
|
||||
yield path
|
||||
|
||||
def force_cache(self):
|
||||
"""parse all option to force data in cache
|
||||
"""
|
||||
context = self.context()
|
||||
if not 'cache' in context.cfgimpl_get_settings():
|
||||
raise ConfigError(_('can force cache only if cache '
|
||||
'is actived in config'))
|
||||
context.cfgimpl_reset_cache()
|
||||
for path in context.cfgimpl_get_description().impl_getpaths(
|
||||
include_groups=True):
|
||||
try:
|
||||
err = context.getattr(path)
|
||||
except PropertiesOptionError as err:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue