tiramisu/tiramisu/value.py

812 lines
34 KiB
Python
Raw Normal View History

2013-02-07 16:20:21 +01:00
# -*- coding: utf-8 -*-
"takes care of the option's values and multi values"
2017-07-04 19:59:42 +02:00
# Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
2013-02-07 16:20:21 +01:00
#
2013-09-22 22:33:09 +02:00
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
2013-02-07 16:20:21 +01:00
#
2013-09-22 22:33:09 +02:00
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
2013-02-07 16:20:21 +01:00
#
2013-09-22 22:33:09 +02:00
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2013-02-07 16:20:21 +01:00
# ____________________________________________________________
from time import time
import sys
import weakref
from .error import ConfigError, SlaveError, PropertiesOptionError
2017-11-23 16:56:14 +01:00
from .setting import owners, expires_time, undefined, forbidden_owners
from .autolib import carry_out_calculation
from .i18n import _
2017-07-24 20:39:01 +02:00
from .option import DynSymLinkOption, Option
2013-02-07 16:20:21 +01:00
2013-04-03 12:20:26 +02:00
2013-08-20 09:47:12 +02:00
class Values(object):
2013-05-23 17:51:50 +02:00
"""The `Config`'s root is indeed in charge of the `Option()`'s values,
but the values are physicaly located here, in `Values`, wich is also
responsible of a caching utility.
2013-05-23 14:55:52 +02:00
"""
__slots__ = ('context', '_p_', '__weakref__')
2013-04-03 12:20:26 +02:00
2013-08-20 22:45:11 +02:00
def __init__(self, context, storage):
2013-02-21 17:07:00 +01:00
"""
Initializes the values's dict.
2013-04-03 12:20:26 +02:00
:param context: the context is the home config's values
2013-05-23 14:55:52 +02:00
2013-02-21 17:07:00 +01:00
"""
self.context = weakref.ref(context)
2013-08-21 14:52:48 +02:00
# the storage type is dictionary or sqlite3
self._p_ = storage
2013-08-20 09:47:12 +02:00
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# 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
(for example we delete a `Config` and we manipulate a reference to
old `SubConfig`, `Values`, `Multi` or `Settings`)
"""
context = self.context()
2017-02-11 17:22:50 +01:00
if context is None:
raise ConfigError(_('the context does not exist anymore'))
return context
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# get value
def get_cached_value(self,
opt,
path=None,
validate=True,
force_permissive=False,
trusted_cached_properties=True,
setting_properties=undefined,
self_properties=undefined,
index=None,
2017-11-23 16:56:14 +01:00
display_warnings=True):
2017-11-20 17:01:36 +01:00
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)
2017-11-23 16:56:14 +01:00
if 'cache' in setting_properties and self._p_.hascache(path, index):
2017-11-20 17:01:36 +01:00
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:
return value
val = self.get_validated_value(opt,
path,
validate,
setting_properties,
self_properties,
index=index,
display_warnings=display_warnings,
2017-11-23 16:56:14 +01:00
force_permissive=force_permissive)
2017-11-20 17:01:36 +01:00
if index is None and 'cache' in setting_properties and \
2017-11-23 16:56:14 +01:00
validate and force_permissive is False \
and trusted_cached_properties is True:
2017-11-20 17:01:36 +01:00
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,
setting_properties,
2017-11-23 16:56:14 +01:00
self_properties=None,
2017-11-20 17:01:36 +01:00
index=None,
display_warnings=True,
2017-11-23 16:56:14 +01:00
force_permissive=False):
2017-11-20 17:01:36 +01:00
"""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()
config_error = None
try:
value = self.getvalue(opt,
path,
index,
2017-11-23 16:56:14 +01:00
setting_properties,
self_properties,
2017-11-20 17:01:36 +01:00
validate,
2017-11-23 16:56:14 +01:00
force_permissive=force_permissive)
2017-11-20 17:01:36 +01:00
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 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:
2017-11-28 22:42:30 +01:00
raise config_error
2017-11-20 17:01:36 +01:00
return value
def getvalue(self,
opt,
path,
index,
2017-11-23 16:56:14 +01:00
setting_properties,
self_properties,
2017-11-20 17:01:36 +01:00
validate,
2017-11-23 16:56:14 +01:00
force_permissive=False):
2017-11-20 17:01:36 +01:00
"""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,
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,
2017-11-23 16:56:14 +01:00
setting_properties,
force_permissive=force_permissive)
2017-11-20 17:01:36 +01:00
2017-11-12 14:33:05 +01:00
def getdefaultvalue(self,
opt,
path,
2017-11-23 16:56:14 +01:00
setting_properties=undefined,
2017-11-12 14:33:05 +01:00
index=None):
"""get default value:
- get meta config value or
- get calculated value or
- get default value
:param opt: the `option.Option()` object
:param path: path for `option.Option()` object
:type path: str
:param index: index of a multi/submulti
:type index: int
:returns: default value
"""
return self._getdefaultvalue(opt,
path,
index,
2017-11-28 22:42:30 +01:00
True,
setting_properties)
2017-11-12 14:33:05 +01:00
def _getdefaultvalue(self,
opt,
path,
index,
validate,
2017-11-23 16:56:14 +01:00
setting_properties,
force_permissive=False):
context = self._getcontext()
2017-11-12 14:33:05 +01:00
def _reset_cache():
# calculated value could be a new value, so reset cache
2017-11-23 16:56:14 +01:00
context.cfgimpl_reset_cache(opt=opt,
path=path)
if self._is_meta(opt,
path,
index,
setting_properties,
force_permissive=force_permissive):
meta = context.cfgimpl_get_meta()
# retrieved value from meta config
try:
value = meta.getattr(path,
index=index,
setting_properties=setting_properties,
force_permissive=force_permissive)
except PropertiesOptionError:
# if properties error, return an other default value
# unexpected error, should not happened
pass
else:
return value
2017-11-12 14:33:05 +01:00
2017-07-16 23:11:12 +02:00
if opt.impl_has_callback():
2017-11-12 14:33:05 +01:00
# if value has callback, calculate value
2017-07-16 23:11:12 +02:00
callback, callback_params = opt.impl_get_callback()
2017-11-12 14:33:05 +01:00
value = carry_out_calculation(opt,
2017-11-23 16:56:14 +01:00
context=context,
2017-07-16 23:11:12 +02:00
callback=callback,
callback_params=callback_params,
2017-11-28 22:42:30 +01:00
setting_properties=setting_properties,
2017-11-12 14:33:05 +01:00
index=index,
validate=validate)
2017-07-16 23:11:12 +02:00
if isinstance(value, list) and index is not None:
2017-11-12 14:33:05 +01:00
# if value is a list and index is set
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# return value only if it's a submulti and not a list of list
_reset_cache()
2017-07-16 23:11:12 +02:00
return value
2017-11-12 14:33:05 +01:00
if len(value) > index:
# return the value for specified index if found
_reset_cache()
2017-07-16 23:11:12 +02:00
return value[index]
2017-11-12 14:33:05 +01:00
# there is no calculate value for this index,
# so return an other default value
elif isinstance(value, list):
# value is a list, but no index specified
_reset_cache()
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value
elif index is not None:
# if not list but with index
_reset_cache()
if opt.impl_is_submulti():
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value
2017-07-16 23:11:12 +02:00
else:
2017-11-12 14:33:05 +01:00
_reset_cache()
# not a list or index is None
if opt.impl_is_submulti():
# return a list of list for a submulti
return [[value]]
elif opt.impl_is_multi():
# return a list for a multi
return [value]
# not a list, return value
2017-07-16 23:11:12 +02:00
return value
2017-11-12 14:33:05 +01:00
# now try to get default value:
# - if opt is a submulti, return a list a list
# - if opt is a multi, return a list
# - default value
value = opt.impl_getdefault()
if opt.impl_is_multi() and index is not None:
2017-11-12 14:33:05 +01:00
# if index, must return good value for this index
if len(value) > index:
value = value[index]
else:
2017-11-12 14:33:05 +01:00
# no value for this index, retrieve default multi value
# default_multi is already a list for submulti
value = opt.impl_getdefault_multi()
return value
2013-02-07 16:20:21 +01:00
2017-11-20 17:01:36 +01:00
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
2015-11-19 22:25:00 +01:00
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
2017-11-20 17:01:36 +01:00
def get_modified_values(self):
return self._p_.get_modified_values()
2015-04-18 23:46:37 +02:00
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# set value
2017-11-20 17:01:36 +01:00
def setvalue(self,
opt,
value,
path,
force_permissive,
index,
setting_properties,
_commit):
2013-04-18 23:06:14 +02:00
context = self._getcontext()
2017-11-12 14:33:05 +01:00
owner = context.cfgimpl_get_settings().getowner()
if 'validator' in setting_properties:
2017-07-16 10:57:43 +02:00
if opt._has_consistencies():
2017-11-12 14:33:05 +01:00
# 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)
2017-07-16 10:57:43 +02:00
else:
2017-11-12 14:33:05 +01:00
tested_context = context
tested_values = self
2017-11-20 17:01:36 +01:00
tested_values.validate_setitem(opt,
value,
path,
force_permissive,
setting_properties,
index)
2015-12-31 18:20:36 +01:00
2017-11-12 14:33:05 +01:00
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()
2017-11-23 16:56:14 +01:00
settings = context.cfgimpl_get_settings()
2017-11-12 14:33:05 +01:00
# First validate properties with this value
2017-11-23 16:56:14 +01:00
properties = settings.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
if 'everything_frozen' in setting_properties or 'frozen' in properties:
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['frozen'],
settings,
datas,
'option')
if settings.validate_mandatory(opt,
index,
value,
2017-11-28 22:42:30 +01:00
setting_properties,
2017-11-23 16:56:14 +01:00
properties):
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['mandatory'],
settings,
datas,
'option')
2017-11-12 14:33:05 +01:00
# Value must be valid for option
2017-11-20 17:01:36 +01:00
opt.impl_validate(value,
context,
display_warnings=False,
force_index=index,
setting_properties=setting_properties)
2017-11-12 14:33:05 +01:00
# 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,
2017-11-20 17:01:36 +01:00
path=path)
2017-11-12 14:33:05 +01:00
if isinstance(value, list):
# copy
value = list(value)
self._p_.setvalue(path,
value,
owner,
index,
commit)
2017-11-20 17:01:36 +01:00
def _is_meta(self,
opt,
path,
2017-11-23 16:56:14 +01:00
index,
2017-11-20 17:01:36 +01:00
setting_properties,
2017-11-23 16:56:14 +01:00
force_permissive=False,
force_owner_is_default=False):
if not force_owner_is_default and self._p_.hasvalue(path,
index=index):
# has already a value, so not meta
return False
context = self._getcontext()
2017-11-23 16:56:14 +01:00
meta = context.cfgimpl_get_meta()
if meta is None:
2017-10-14 13:33:25 +02:00
return False
2017-11-23 16:56:14 +01:00
if opt.impl_is_master_slaves('slave'):
2017-12-02 22:53:57 +01:00
master = opt.impl_get_master_slaves().getmaster()
2017-11-23 16:56:14 +01:00
masterp = master.impl_getpath(context)
# slave could be a "meta" only if master hasn't value
if self._p_.hasvalue(masterp,
index=index):
return False
return not meta.cfgimpl_get_values().is_default_owner(opt,
path,
setting_properties,
index=index,
force_permissive=force_permissive)
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# owner
def getowner(self,
opt,
path,
setting_properties,
index=None,
force_permissive=False):
2013-08-21 11:09:11 +02:00
"""
retrieves the option's owner
2013-08-21 14:52:48 +02:00
:param opt: the `option.Option` object
:param force_permissive: behaves as if the permissive property
was present
2013-08-21 11:09:11 +02:00
:returns: a `setting.owners.Owner` object
"""
2017-11-23 16:56:14 +01:00
if opt.impl_is_symlinkoption() and \
2014-06-19 23:22:39 +02:00
not isinstance(opt, DynSymLinkOption):
2017-11-23 16:56:14 +01:00
opt = opt.impl_getopt()
2017-11-12 14:33:05 +01:00
return self._getowner(opt,
path,
2017-11-20 17:01:36 +01:00
setting_properties,
2017-11-12 14:33:05 +01:00
index=index,
force_permissive=force_permissive)
def _getowner(self,
opt,
path,
2017-11-20 17:01:36 +01:00
setting_properties,
2017-11-12 14:33:05 +01:00
force_permissive=False,
validate_meta=undefined,
self_properties=undefined,
only_default=False,
2015-11-19 22:25:00 +01:00
index=None):
2015-05-03 09:56:03 +02:00
"""get owner of an option
"""
2017-11-23 16:56:14 +01:00
#FIXME: validate_meta ne marche que si == False ou undefined !
if validate_meta is not False and validate_meta is not undefined:
raise Exception('poeut')
2017-11-28 22:42:30 +01:00
#if not isinstance(opt, Option) and not isinstance(opt,
# DynSymLinkOption):
# raise ConfigError(_('owner only avalaible for an option'))
#FIXME pas defaut fait ??
context = self._getcontext()
2015-10-29 09:03:13 +01:00
if self_properties is undefined:
2017-11-20 17:01:36 +01:00
self_properties = context.cfgimpl_get_settings().getproperties(opt,
path,
setting_properties)
2015-10-29 09:03:13 +01:00
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
2017-11-23 16:56:14 +01:00
if only_default:
if self._p_.hasvalue(path,
index):
owner = undefined
else:
2017-11-23 16:56:14 +01:00
owner = owners.default
else:
owner = self._p_.getowner(path,
owners.default,
index=index)
if owner is owners.default and validate_meta is not False:
if validate_meta is undefined:
validate_meta = self._is_meta(opt,
path,
index,
setting_properties,
force_permissive=force_permissive,
force_owner_is_default=True)
if validate_meta:
owner = owners.meta
2013-05-02 11:34:57 +02:00
return owner
2013-04-03 12:20:26 +02:00
2017-11-20 17:01:36 +01:00
def setowner(self,
path,
owner,
index=None):
2013-08-21 11:09:11 +02:00
"""
sets a owner to an option
2013-08-21 14:52:48 +02:00
:param opt: the `option.Option` object
2013-08-21 11:09:11 +02:00
:param owner: a valid owner, that is a `setting.owners.Owner` object
"""
2017-02-11 17:22:50 +01:00
if not isinstance(owner, owners.Owner):
2017-11-23 16:56:14 +01:00
raise TypeError(_("invalid owner {0}").format(str(owner)))
if owner in forbidden_owners:
raise ConfigError(_('set owner "{0}" is forbidden').format(str(owner)))
2017-11-12 14:33:05 +01:00
if not self._p_.hasvalue(path):
2017-10-22 09:48:08 +02:00
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(path, owner))
2017-11-12 14:33:05 +01:00
self._p_.setowner(path, owner, index=index)
2013-04-03 12:20:26 +02:00
2017-11-20 17:01:36 +01:00
def is_default_owner(self,
opt,
path,
setting_properties,
2017-11-23 16:56:14 +01:00
validate_meta=undefined,
2017-11-20 17:01:36 +01:00
self_properties=undefined,
index=None,
force_permissive=False):
2017-11-12 14:33:05 +01:00
owner = self._getowner(opt,
path,
2017-11-20 17:01:36 +01:00
setting_properties,
2017-11-12 14:33:05 +01:00
validate_meta=validate_meta,
self_properties=self_properties,
only_default=True,
index=index,
force_permissive=force_permissive)
return owner == owners.default
2013-02-21 17:07:00 +01:00
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# reset
def reset(self,
opt,
path,
setting_properties,
validate=True,
_commit=True,
force_permissive=False):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
hasvalue = self._p_.hasvalue(path)
if validate and hasvalue and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(opt,
path,
setting_properties,
validate=False)
2017-11-23 16:56:14 +01:00
#FIXME ce n'est pas deja fait dans le reset ?
#sinon c'est un validate_properties qu'il faut faire ...
#fake_value.get_cached_value(opt,
# path,
# setting_properties=setting_properties,
# force_permissive=force_permissive)
2017-11-20 17:01:36 +01:00
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(opt,
self,
setting_properties,
_commit=_commit,
force_permissive=force_permissive)
if hasvalue:
if 'force_store_value' in setting.getproperties(opt,
path,
setting_properties,
apply_requires=False):
value = self._getdefaultvalue(opt,
path,
None,
validate,
2017-11-23 16:56:14 +01:00
setting_properties)
2017-11-20 17:01:36 +01:00
self._setvalue(opt,
path,
value,
owners.forced,
None,
commit=_commit)
else:
self._p_.resetvalue(path,
_commit)
context.cfgimpl_reset_cache(opt=opt,
path=path)
def reset_slave(self,
opt,
path,
index,
setting_properties,
validate=True,
force_permissive=False):
context = self._getcontext()
if validate and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset_slave(opt,
path,
index,
setting_properties,
validate=False)
fake_value.get_cached_value(opt,
path,
index=index,
setting_properties=setting_properties,
force_permissive=force_permissive)
self._p_.resetvalue_index(path, index)
def reset_master(self,
subconfig,
opt,
path,
index,
force_permissive,
setting_properties):
current_value = self.get_cached_value(opt,
path,
setting_properties=setting_properties,
force_permissive=force_permissive)
current_value.pop(index)
self.setvalue(opt,
current_value,
path,
force_permissive=force_permissive,
index=None,
setting_properties=setting_properties,
_commit=True)
2017-12-02 22:53:57 +01:00
subconfig.cfgimpl_get_description().pop(self,
2017-11-28 22:42:30 +01:00
index,
setting_properties,
2017-12-02 22:53:57 +01:00
force_permissive)
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# information
2017-11-20 17:01:36 +01:00
def set_information(self, key, value):
"""updates the information's attribute
:param key: information's key (ex: "help", "doc"
:param value: information's value (ex: "the help string")
"""
self._p_.set_information(key, value)
def get_information(self, key, default=undefined):
"""retrieves one information's item
:param key: the item string (ex: "help")
"""
2015-12-28 22:00:46 +01:00
return self._p_.get_information(key, default)
def del_information(self, key, raises=True):
self._p_.del_information(key, raises)
2017-11-20 17:01:36 +01:00
#______________________________________________________________________
# mandatory warnings
def mandatory_warnings(self, force_permissive=True):
"""convenience function to trace Options that are mandatory and
where no value has been set
2015-10-29 09:03:13 +01:00
:returns: generator of mandatory Option's path
"""
2015-10-29 09:03:13 +01:00
context = self._getcontext()
settings = context.cfgimpl_get_settings()
2017-11-20 17:01:36 +01:00
setting_properties = context.cfgimpl_get_settings().get_context_properties()
setting_properties.update(['mandatory', 'empty'])
def _is_properties_option(err, path):
2017-11-13 22:45:53 +01:00
#FIXME hum ...
if not isinstance(err, Exception):
pass
elif isinstance(err, PropertiesOptionError):
if err.proptype == ['mandatory']:
return path
elif isinstance(err, ConfigError):
#assume that uncalculated value is an empty value
return path
else:
raise err
2015-10-29 09:03:13 +01:00
def _mandatory_warnings(description, currpath=None):
if currpath is None:
currpath = []
2015-05-03 09:56:03 +02:00
for opt in description._impl_getchildren(context=context):
2015-10-29 09:03:13 +01:00
name = opt.impl_getname()
path = '.'.join(currpath + [name])
2014-06-19 23:22:39 +02:00
if opt.impl_is_optiondescription():
2017-11-23 16:56:14 +01:00
#FIXME ?
2015-12-30 22:32:07 +01:00
if not settings.validate_properties(opt, True, False, path=path,
force_permissive=True,
2015-12-30 22:32:07 +01:00
setting_properties=setting_properties):
2015-10-29 09:03:13 +01:00
for path in _mandatory_warnings(opt, currpath + [name]):
yield path
else:
2017-11-23 16:56:14 +01:00
if opt.impl_is_symlinkoption() and \
2015-10-29 09:03:13 +01:00
not isinstance(opt, DynSymLinkOption):
continue
2017-11-20 17:01:36 +01:00
self_properties = settings.getproperties(opt,
path,
setting_properties=setting_properties)
if 'mandatory' in self_properties or 'empty' in self_properties:
2017-11-12 14:33:05 +01:00
err = self.get_cached_value(opt, path=path,
trusted_cached_properties=False,
force_permissive=True,
setting_properties=setting_properties,
self_properties=self_properties,
validate=True,
display_warnings=False)
if opt.impl_is_master_slaves('slave') and isinstance(err, list):
for val in err:
ret = _is_properties_option(val, path)
if ret is not None:
yield ret
break
2016-01-03 21:18:52 +01:00
else:
ret = _is_properties_option(err, path)
if ret is not None:
yield ret
2015-10-29 09:03:13 +01:00
2017-06-16 18:25:01 +02:00
descr = context.cfgimpl_get_description()
2015-10-29 09:03:13 +01:00
for path in _mandatory_warnings(descr):
yield path