tiramisu/tiramisu/value.py

877 lines
38 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
from .setting import owners, expires_time, undefined
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
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-12 14:33:05 +01:00
def getdefaultvalue(self,
opt,
path,
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,
True,
self._getcontext())
def _getdefaultvalue(self,
opt,
path,
index,
validate,
_orig_context):
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'))
#FIXME with_meta should be calculated here...
with_meta = True
if with_meta:
meta = self._getcontext().cfgimpl_get_meta()
if meta is not None:
2017-11-12 14:33:05 +01:00
# retrieved value from meta config
2017-11-13 22:45:53 +01:00
try:
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
except PropertiesOptionError:
2017-11-12 14:33:05 +01:00
# if properties error, return an other default value
2017-11-13 22:45:53 +01:00
# unexpected error, should not happened
pass
2016-01-03 21:18:52 +01:00
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,
context=_orig_context,
2017-07-16 23:11:12 +02:00
callback=callback,
callback_params=callback_params,
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-12 14:33:05 +01:00
def _getvalue(self,
opt,
path,
self_properties,
index,
validate,
_orig_context):
2015-11-19 22:25:00 +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
2017-04-19 21:47:12 +02:00
if index is None or not opt.impl_is_master_slaves('slave'):
_index = None
else:
_index = index
2017-11-12 14:33:05 +01:00
owner, value = self._p_.getowner(path,
owners.default,
only_default=True,
index=_index,
with_value=True)
2017-07-11 22:31:58 +02:00
is_default = owner == owners.default
2015-11-19 22:25:00 +01:00
if not is_default and not force_default:
2017-07-11 22:31:58 +02:00
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
2015-11-19 22:25:00 +01:00
else:
2017-07-11 22:31:58 +02:00
return value
2017-11-12 14:33:05 +01:00
return self._getdefaultvalue(opt,
path,
index,
validate,
_orig_context)
2015-11-19 22:25:00 +01:00
2013-08-14 23:06:31 +02:00
def get_modified_values(self):
2013-08-20 09:47:12 +02:00
return self._p_.get_modified_values()
2013-08-14 23:06:31 +02:00
def __contains__(self, opt):
2013-08-21 14:52:48 +02:00
"""
implements the 'in' keyword syntax in order provide a pythonic way
to kow if an option have a value
:param opt: the `option.Option()` object
"""
2014-06-19 23:22:39 +02:00
path = opt.impl_getpath(self._getcontext())
return self._contains(path)
2017-11-12 14:33:05 +01:00
def _contains(self, path):
return self._p_.hasvalue(path)
2013-08-14 23:06:31 +02:00
2017-11-12 14:33:05 +01:00
def reset(self,
opt,
path,
setting_properties,
validate=True,
_commit=True,
2017-10-22 09:48:08 +02:00
force_permissive=False):
2017-11-12 14:33:05 +01:00
context = self._getcontext()
2015-12-17 22:41:57 +01:00
setting = context.cfgimpl_get_settings()
2017-11-12 14:33:05 +01:00
hasvalue = self._contains(path)
if validate and hasvalue and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
2017-11-12 14:33:05 +01:00
fake_value.reset(opt,
path,
setting_properties,
validate=False)
ret = fake_value.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
2016-10-14 22:20:14 +02:00
if isinstance(ret, Exception):
raise ret
if opt.impl_is_master_slaves('master'):
2017-11-12 14:33:05 +01:00
opt.impl_get_master_slaves().reset(opt,
self,
setting_properties,
_commit=_commit,
2017-10-22 09:48:08 +02:00
force_permissive=force_permissive)
if hasvalue:
if 'force_store_value' in setting._getproperties(opt=opt,
path=path,
2017-11-12 14:33:05 +01:00
setting_properties=setting_properties,
read_write=False,
apply_requires=False):
2017-11-12 14:33:05 +01:00
value = self._getdefaultvalue(opt,
path,
True,
undefined,
validate,
context)
2017-02-11 17:22:50 +01:00
if isinstance(value, Exception): # pragma: no cover
2016-10-14 22:20:14 +02:00
raise value
2017-11-12 14:33:05 +01:00
self._setvalue(opt,
path,
value,
owners.forced,
None,
commit=_commit)
else:
2017-11-12 14:33:05 +01:00
self._p_.resetvalue(path,
_commit)
context.cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
def reset_slave(self,
opt,
path,
index,
setting_properties,
validate=True,
force_permissive=False):
2013-02-26 14:56:15 +01:00
2017-11-12 14:33:05 +01:00
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)
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
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,
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
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
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
2013-04-18 23:06:14 +02:00
def __getitem__(self, opt):
"enables us to use the pythonic dictionary-like access to values"
2017-11-12 14:33:05 +01:00
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):
2015-10-29 09:03:13 +01:00
context = self._getcontext()
2015-12-17 22:41:57 +01:00
settings = context.cfgimpl_get_settings()
if path is None:
2015-10-29 09:03:13 +01:00
path = opt.impl_getpath(context)
2013-09-07 17:25:22 +02:00
ntime = None
if setting_properties is undefined:
2015-12-17 22:41:57 +01:00
setting_properties = settings._getproperties(read_write=False)
2015-10-29 09:03:13 +01:00
if self_properties is undefined:
2017-11-12 14:33:05 +01:00
self_properties = settings._getproperties(opt,
path,
2015-12-17 22:41:57 +01:00
read_write=False,
setting_properties=setting_properties,
index=index)
2017-07-16 23:11:12 +02:00
if 'cache' in setting_properties and self._p_.hascache(path, index) and \
_orig_context is undefined:
if 'expire' in setting_properties:
2013-09-07 17:25:22 +02:00
ntime = int(time())
is_cached, value = self._p_.getcache(path, ntime, None)
if index:
value = value[index]
2013-08-14 23:06:31 +02:00
if is_cached:
2017-11-12 14:33:05 +01:00
#if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
# value = Multi(value, self.context, opt, path)
2015-12-14 23:37:15 +01:00
if not trusted_cached_properties:
2015-12-17 22:41:57 +01:00
# revalidate properties (because of not default properties)
2017-11-12 14:33:05 +01:00
props = settings.validate_properties(opt,
False,
False,
value=value,
2015-12-30 22:32:07 +01:00
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
index=index)
if props:
2016-10-14 22:20:14 +02:00
return props
2013-04-18 23:06:14 +02:00
return value
2017-11-12 14:33:05 +01:00
#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:
2017-11-12 14:33:05 +01:00
_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)
2016-01-06 22:37:11 +01:00
if isinstance(val, Exception):
2016-10-14 22:20:14 +02:00
return val
2017-11-12 14:33:05 +01:00
if index is None and 'cache' in setting_properties and \
2015-12-17 22:41:57 +01:00
validate and validate_properties and force_permissive is False \
2017-07-16 23:11:12 +02:00
and trusted_cached_properties is True and _orig_context is undefined:
if 'expire' in setting_properties:
2013-09-07 17:25:22 +02:00
if ntime is None:
ntime = int(time())
ntime = ntime + expires_time
self._p_.setcache(path, val, ntime, None)
2013-04-18 23:06:14 +02:00
return val
2017-11-12 14:33:05 +01:00
def _get_validated_value(self,
opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
2016-11-19 19:16:31 +01:00
self_properties,
2017-11-12 14:33:05 +01:00
index=None,
2016-11-19 19:16:31 +01:00
check_frozen=False,
2017-11-12 14:33:05 +01:00
display_warnings=True,
2017-07-16 23:11:12 +02:00
_orig_context=undefined):
2014-04-25 22:57:08 +02: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()
setting = context.cfgimpl_get_settings()
2016-01-03 21:18:52 +01:00
config_error = None
2017-11-13 22:45:53 +01:00
try:
value = self._getvalue(opt,
path,
self_properties,
index,
validate,
_orig_context)
except ConfigError as value:
2016-11-20 14:32:06 +01:00
value_error = True
2017-11-13 22:45:53 +01:00
# 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
2015-11-19 22:25:00 +01:00
else:
2016-11-20 14:32:06 +01:00
value_error = False
if validate:
2017-11-12 14:33:05 +01:00
err = opt.impl_validate(value,
context,
'validator' in setting_properties,
2017-02-11 17:22:50 +01:00
force_index=index,
2016-11-20 14:32:06 +01:00
display_error=True,
2017-07-11 22:31:58 +02:00
display_warnings=False,
setting_properties=setting_properties)
if err:
2015-04-18 23:46:37 +02:00
config_error = err
value = None
if validate_properties:
2015-10-29 09:03:13 +01:00
if config_error is not None:
# should not raise PropertiesOptionError if option is
# mandatory
val_props = undefined
else:
val_props = value
2017-11-12 14:33:05 +01:00
props = setting.validate_properties(opt,
False,
check_frozen,
value=val_props,
2015-12-30 22:32:07 +01:00
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
index=index)
if props:
2016-10-14 22:20:14 +02:00
return props
2016-11-20 14:32:06 +01:00
if not value_error and validate and display_warnings:
2017-11-12 14:33:05 +01:00
opt.impl_validate(value,
context,
2016-11-20 14:32:06 +01:00
'validator' in setting_properties,
2017-02-11 17:22:50 +01:00
force_index=index,
2016-11-20 14:32:06 +01:00
display_error=False,
2017-07-04 19:59:42 +02:00
display_warnings=display_warnings,
2017-07-11 22:31:58 +02:00
setting_properties=setting_properties)
if config_error is not None:
2016-10-14 22:20:14 +02:00
return config_error
return value
2017-11-12 14:33:05 +01:00
def setitem(self,
opt,
value,
path,
force_permissive,
not_raises,
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
props = tested_values.validate_setitem(opt,
value,
path,
force_permissive,
setting_properties,
index)
if props:
if not not_raises:
raise props
return props
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-12 14:33:05 +01:00
# 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)
2015-12-31 18:20:36 +01:00
if props:
2017-11-12 14:33:05 +01:00
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()
2017-10-14 13:33:25 +02:00
if context.cfgimpl_get_meta() is None:
return False
setting = context.cfgimpl_get_settings()
2015-10-29 09:03:13 +01:00
self_properties = setting._getproperties(opt, path, read_write=False)
2017-10-14 13:33:25 +02:00
return self.is_default_owner(opt, path=path, validate_properties=True,
validate_meta=False, index=None,
force_permissive=force_permissive)
2017-11-12 14:33:05 +01:00
def getowner(self, opt, 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-07-24 20:39:01 +02:00
if opt._is_symlinkoption() and \
2014-06-19 23:22:39 +02:00
not isinstance(opt, DynSymLinkOption):
2014-11-10 09:13:44 +01:00
opt = opt._impl_getopt()
2014-06-19 23:22:39 +02:00
path = opt.impl_getpath(self._getcontext())
2017-11-12 14:33:05 +01:00
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,
2015-11-19 22:25:00 +01:00
index=None):
2015-05-03 09:56:03 +02:00
"""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()
2015-10-29 09:03:13 +01:00
if self_properties is undefined:
self_properties = context.cfgimpl_get_settings()._getproperties(
2015-05-03 09:56:03 +02:00
opt, path, read_write=False)
2015-10-29 09:03:13 +01:00
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if validate_properties:
2017-11-12 14:33:05 +01:00
value = self.get_cached_value(opt,
path=path,
force_permissive=force_permissive,
self_properties=self_properties,
index=index)
2016-10-14 22:20:14 +02:00
if isinstance(value, Exception):
raise value
2016-11-19 19:16:31 +01:00
2017-11-12 14:33:05 +01:00
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)
2017-11-12 14:33:05 +01:00
validate_meta = self._is_meta(master, masterp)
else:
validate_meta = True
2017-10-14 13:33:25 +02:00
if validate_meta and owner is owners.default:
meta = context.cfgimpl_get_meta()
2017-10-14 13:33:25 +02:00
if meta is not None:
2017-11-12 14:33:05 +01:00
owner = meta.cfgimpl_get_values()._getowner(opt,
path,
2015-11-19 22:25:00 +01:00
validate_properties=validate_properties,
force_permissive=force_permissive,
self_properties=self_properties,
2017-11-12 14:33:05 +01:00
only_default=only_default,
index=index)
2013-05-02 11:34:57 +02:00
return owner
2013-04-03 12:20:26 +02:00
2017-10-22 09:48:08 +02:00
def setowner(self, opt, owner, index=None, force_permissive=False):
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):
2013-04-13 23:09:05 +02:00
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
2014-06-19 23:22:39 +02:00
path = opt.impl_getpath(self._getcontext())
2015-12-30 22:32:07 +01:00
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False,
True,
2016-01-25 16:22:28 +01:00
path,
2017-10-22 09:48:08 +02:00
index=index,
force_permissive=force_permissive)
2015-12-30 22:32:07 +01:00
if props:
raise props
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-10-14 13:33:25 +02:00
def is_default_owner(self, opt, path=None, validate_properties=True,
validate_meta=True, index=None,
force_permissive=False):
2013-04-03 12:20:26 +02:00
"""
:param config: *must* be only the **parent** config
(not the toplevel config)
:return: boolean
"""
2017-10-14 13:33:25 +02:00
if path is None:
path = opt.impl_getpath(self._getcontext())
2017-11-12 14:33:05 +01:00
return self._is_default_owner(opt,
path,
validate_properties=validate_properties,
2017-11-12 14:33:05 +01:00
validate_meta=validate_meta,
index=index,
force_permissive=force_permissive)
2017-11-12 14:33:05 +01:00
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
2013-02-21 17:07:00 +01:00
# information
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)
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()
2015-12-14 23:37:15 +01:00
setting_properties = context.cfgimpl_get_settings()._getproperties()
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():
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-07-24 20:39:01 +02:00
if opt._is_symlinkoption() and \
2015-10-29 09:03:13 +01:00
not isinstance(opt, DynSymLinkOption):
continue
self_properties = settings._getproperties(opt, path,
2015-10-29 09:03:13 +01:00
read_write=False,
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
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):
2017-11-13 22:45:53 +01:00
try:
err = context.getattr(path)
except PropertiesOptionError as err:
pass