async version of tiramisu
This commit is contained in:
@ -18,7 +18,7 @@ from .function import calc_value, calc_value_property_help, valid_ip_netmask, \
|
||||
valid_network_netmask, valid_in_network, valid_broadcast, \
|
||||
valid_not_equal
|
||||
from .autolib import Calculation, Params, ParamOption, ParamSelfOption, ParamValue, \
|
||||
ParamIndex, ParamContext, ParamSuffix
|
||||
ParamIndex, ParamSuffix
|
||||
from .option import *
|
||||
from .error import APIError
|
||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||
@ -34,7 +34,6 @@ allfuncs = ['Calculation',
|
||||
'ParamSelfOption',
|
||||
'ParamValue',
|
||||
'ParamIndex',
|
||||
'ParamContext',
|
||||
'ParamSuffix',
|
||||
'MetaConfig',
|
||||
'MixConfig',
|
||||
|
1562
tiramisu/api.py
1562
tiramisu/api.py
@ -18,6 +18,7 @@ from inspect import ismethod, getdoc, signature
|
||||
from time import time
|
||||
from typing import List, Set, Any, Optional, Callable, Union, Dict
|
||||
from warnings import catch_warnings, simplefilter
|
||||
from functools import wraps
|
||||
|
||||
|
||||
from .error import APIError, ConfigError, LeadershipError, PropertiesOptionError, ValueErrorWarning
|
||||
@ -27,6 +28,7 @@ from .setting import ConfigBag, OptionBag, owners, groups, Undefined, undefined,
|
||||
from .config import KernelConfig, SubConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig
|
||||
from .option import ChoiceOption, RegexpOption, OptionDescription
|
||||
from .todict import TiramisuDict
|
||||
from .asyncinit import asyncinit
|
||||
|
||||
|
||||
TIRAMISU_VERSION = 3
|
||||
@ -61,7 +63,7 @@ class TiramisuHelp:
|
||||
display(self._tmpl_help.format('forcepermissive', _('Access to option without verifying permissive properties')).expandtabs(max_len + 10))
|
||||
display(self._tmpl_help.format('unrestraint', _('Access to option without property restriction')).expandtabs(max_len + 10))
|
||||
display()
|
||||
if isinstance(self, TiramisuDispatcher):
|
||||
if isinstance(self, TiramisuDispatcherOption):
|
||||
doc = _(getdoc(self.__call__))
|
||||
display(_('Call: {}').format(doc))
|
||||
display()
|
||||
@ -82,31 +84,45 @@ class CommonTiramisu(TiramisuHelp):
|
||||
_allow_optiondescription = True
|
||||
_validate_properties = True
|
||||
|
||||
def _get_option(self) -> Any:
|
||||
async def _get_option(self) -> Any:
|
||||
if not self._subconfig:
|
||||
config_bag = self._option_bag.config_bag
|
||||
try:
|
||||
subconfig, name = await config_bag.context.cfgimpl_get_home_by_path(self._option_bag.path,
|
||||
config_bag,
|
||||
validate_properties=self._validate_properties)
|
||||
except AssertionError as err:
|
||||
raise APIError(str(err))
|
||||
except Exception as err:
|
||||
raise err
|
||||
self._subconfig = subconfig
|
||||
self._name = name
|
||||
option = self._option_bag.option
|
||||
if option is None:
|
||||
option = self._subconfig.cfgimpl_get_description().get_child(self._name,
|
||||
self._option_bag.config_bag,
|
||||
self._subconfig.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
self._option_bag.config_bag)
|
||||
option = await self._subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
self._subconfig.cfgimpl_get_path())
|
||||
self._option_bag.option = option
|
||||
# Calculate option's properties
|
||||
|
||||
settings = config_bag.context.cfgimpl_get_settings()
|
||||
self._option_bag.properties = await settings.getproperties(self._option_bag)
|
||||
if self._validate_properties:
|
||||
option_bag.config_bag.context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
self._option_bag = option_bag
|
||||
await settings.validate_properties(self._option_bag)
|
||||
index = self._option_bag.index
|
||||
if index is not None:
|
||||
if option.impl_is_optiondescription() or not option.impl_is_follower():
|
||||
self._option_bag.option = None
|
||||
raise APIError('index must be set only with a follower option')
|
||||
self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
self._length = await self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
if index >= self._length:
|
||||
self._option_bag.option = None
|
||||
raise LeadershipError(_('index "{}" is greater than the leadership length "{}" '
|
||||
'for option "{}"').format(index,
|
||||
self._length,
|
||||
option.impl_get_display_name()))
|
||||
if not self._allow_optiondescription and option.impl_is_optiondescription():
|
||||
self._option_bag.option = None
|
||||
raise APIError(_('option must not be an optiondescription'))
|
||||
return option
|
||||
|
||||
@ -117,28 +133,12 @@ class CommonTiramisuOption(CommonTiramisu):
|
||||
_validate_properties = False
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
subconfig: Union[KernelConfig, SubConfig],
|
||||
option_bag: OptionBag,
|
||||
config: 'Config'=None) -> None:
|
||||
option_bag: OptionBag) -> None:
|
||||
self._option_bag = option_bag
|
||||
self._name = name
|
||||
self._subconfig = subconfig
|
||||
# for help()
|
||||
if option_bag is not None and self._option_bag.config_bag.context.impl_type != 'group':
|
||||
self._get_option()
|
||||
if option_bag.config_bag is not None and self._follower_need_index:
|
||||
self._test_follower_index()
|
||||
|
||||
def _test_follower_index(self) -> None:
|
||||
option = self._option_bag.option
|
||||
if not option.impl_is_optiondescription() and \
|
||||
self._option_bag.index is None and \
|
||||
option.impl_is_follower():
|
||||
raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.option.impl_get_display_name()))
|
||||
self._subconfig = None
|
||||
|
||||
def __getattr__(self, name):
|
||||
raise APIError(_('unknown method {} in {}').format(name, self.__class__.__name__))
|
||||
raise APIError(_('unknown method "{}" in "{}"').format(name, self.__class__.__name__))
|
||||
|
||||
|
||||
class _TiramisuOptionOptionDescription(CommonTiramisuOption):
|
||||
@ -148,147 +148,145 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
|
||||
_validate_properties = False
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
subconfig: Union[KernelConfig, SubConfig],
|
||||
option_bag: OptionBag,
|
||||
config: "Subconfig") -> None:
|
||||
super().__init__(name, subconfig, option_bag)
|
||||
self._config = config
|
||||
option_bag: OptionBag):
|
||||
super().__init__(option_bag)
|
||||
self._config = option_bag.config_bag.context
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get Tiramisu option"""
|
||||
return self._option_bag.option
|
||||
return await self._get_option()
|
||||
|
||||
def type(self):
|
||||
return self._option_bag.option.impl_get_group_type()
|
||||
async def type(self):
|
||||
option = await self._get_option()
|
||||
return option.impl_get_group_type()
|
||||
|
||||
def isleadership(self):
|
||||
async def isleadership(self):
|
||||
"""Test if option is a leader or a follower"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_leadership()
|
||||
|
||||
def doc(self):
|
||||
async def doc(self):
|
||||
"""Get option document"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_get_display_name()
|
||||
|
||||
def description(self):
|
||||
async def description(self):
|
||||
"""Get option description"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_get_information('doc', None)
|
||||
|
||||
def name(self,
|
||||
async def name(self,
|
||||
follow_symlink: bool=False) -> str:
|
||||
"""Get option name"""
|
||||
option = await self._get_option()
|
||||
if not follow_symlink or \
|
||||
self.isoptiondescription() or \
|
||||
not self.issymlinkoption():
|
||||
return self._name
|
||||
await self.isoptiondescription() or \
|
||||
not await self.issymlinkoption():
|
||||
return option.impl_getname()
|
||||
else:
|
||||
option = self._option_bag.option
|
||||
return option.impl_getopt().impl_getname()
|
||||
|
||||
def path(self) -> str:
|
||||
async def path(self) -> str:
|
||||
"""Get option path"""
|
||||
return self._option_bag.path
|
||||
|
||||
def has_dependency(self, self_is_dep=True):
|
||||
async def has_dependency(self, self_is_dep=True):
|
||||
"""Test if option has dependency"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_has_dependency(self_is_dep)
|
||||
|
||||
def isoptiondescription(self):
|
||||
async def isoptiondescription(self):
|
||||
"""Test if option is an optiondescription"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_optiondescription()
|
||||
|
||||
def properties(self,
|
||||
only_raises=False,
|
||||
uncalculated=False):
|
||||
async def properties(self,
|
||||
only_raises=False,
|
||||
uncalculated=False):
|
||||
"""Get properties for an option"""
|
||||
settings = self._option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
option = await self._get_option()
|
||||
if uncalculated:
|
||||
return settings.getproperties(self._option_bag,
|
||||
uncalculated=True)
|
||||
return await settings.getproperties(self._option_bag,
|
||||
uncalculated=True)
|
||||
if not only_raises:
|
||||
return settings.getproperties(self._option_bag,
|
||||
apply_requires=False)
|
||||
return await settings.getproperties(self._option_bag,
|
||||
apply_requires=False)
|
||||
# do not check cache properties/permissives which are not save (unrestraint, ...)
|
||||
return settings.calc_raises_properties(self._option_bag,
|
||||
apply_requires=False)
|
||||
return await settings.calc_raises_properties(self._option_bag,
|
||||
apply_requires=False)
|
||||
|
||||
def __call__(self,
|
||||
name: str,
|
||||
index: Optional[int]=None) -> 'TiramisuOption':
|
||||
"""Select an option by path"""
|
||||
path = self._option_bag.path + '.' + name
|
||||
return TiramisuOption(name,
|
||||
path,
|
||||
return TiramisuOption(path,
|
||||
index,
|
||||
self._config,
|
||||
self._option_bag.config_bag)
|
||||
|
||||
|
||||
class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
||||
class TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
||||
"""Manage option"""
|
||||
def ismulti(self):
|
||||
async def ismulti(self):
|
||||
"""Test if option could have multi value"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_multi()
|
||||
|
||||
def issubmulti(self):
|
||||
async def issubmulti(self):
|
||||
"""Test if option could have submulti value"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_submulti()
|
||||
|
||||
def isleader(self):
|
||||
async def isleader(self):
|
||||
"""Test if option is a leader"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_leader()
|
||||
|
||||
def isfollower(self):
|
||||
async def isfollower(self):
|
||||
"""Test if option is a follower"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_is_follower()
|
||||
|
||||
def issymlinkoption(self) -> bool:
|
||||
option = self._option_bag.option
|
||||
async def issymlinkoption(self) -> bool:
|
||||
option = await self._get_option()
|
||||
return option.impl_is_symlinkoption()
|
||||
|
||||
def default(self):
|
||||
async def default(self):
|
||||
"""Get default value for an option (not for optiondescription)"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_getdefault()
|
||||
|
||||
def defaultmulti(self):
|
||||
async def defaultmulti(self):
|
||||
"""Get default value when added a value for a multi option (not for optiondescription)"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
ret = option.impl_getdefault_multi()
|
||||
if ret is None and option.impl_is_multi() and option.impl_has_callback() and not self.isfollower():
|
||||
callback, callback_params = option.impl_get_callback()
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
value = values.carry_out_calculation(self._option_bag,
|
||||
callback,
|
||||
callback_params)
|
||||
value = await values.carry_out_calculation(self._option_bag,
|
||||
callback,
|
||||
callback_params)
|
||||
if not isinstance(value, list):
|
||||
ret = value
|
||||
return ret
|
||||
|
||||
def callbacks(self):
|
||||
async def callbacks(self):
|
||||
"""Get callbacks for an option (not for optiondescription)"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_get_callback()
|
||||
|
||||
def validator(self):
|
||||
async def validator(self):
|
||||
"""Get validator for an option (not for optiondescription)"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_get_validator()
|
||||
|
||||
def type(self):
|
||||
return self._option_bag.option.get_type()
|
||||
async def type(self):
|
||||
option = await self._get_option()
|
||||
return option.get_type()
|
||||
|
||||
def pattern(self) -> str:
|
||||
option = self._option_bag.option
|
||||
async def pattern(self) -> str:
|
||||
option = await self._get_option()
|
||||
type = option.get_type()
|
||||
if isinstance(option, RegexpOption):
|
||||
return option._regexp.pattern
|
||||
@ -302,121 +300,91 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
||||
return r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
|
||||
|
||||
|
||||
class TiramisuOptionOption(CommonTiramisuOption):
|
||||
"""Manage option"""
|
||||
_allow_optiondescription = True
|
||||
_follower_need_index = False
|
||||
|
||||
def __new__(cls,
|
||||
name,
|
||||
subconfig,
|
||||
option_bag,
|
||||
config):
|
||||
if option_bag.option.impl_is_optiondescription():
|
||||
return _TiramisuOptionOptionDescription(name=name,
|
||||
subconfig=subconfig,
|
||||
option_bag=option_bag,
|
||||
config=config)
|
||||
else:
|
||||
return _TiramisuOptionOption(name=name,
|
||||
subconfig=subconfig,
|
||||
option_bag=option_bag,
|
||||
config=config)
|
||||
|
||||
|
||||
class TiramisuOptionOwner(CommonTiramisuOption):
|
||||
#FIXME optiondescription must not have Owner!
|
||||
"""Manage option's owner"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
subconfig: Union[KernelConfig, SubConfig],
|
||||
option_bag: OptionBag,
|
||||
config: Optional['SubConfig']) -> None:
|
||||
option_bag: OptionBag) -> None:
|
||||
|
||||
super().__init__(name,
|
||||
subconfig,
|
||||
option_bag)
|
||||
super().__init__(option_bag)
|
||||
if option_bag is not None:
|
||||
# for help()
|
||||
self._values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get owner for a specified option"""
|
||||
self._option_bag.option
|
||||
return self._values.getowner(self._option_bag)
|
||||
await self._get_option()
|
||||
return await self._values.getowner(self._option_bag)
|
||||
|
||||
def isdefault(self):
|
||||
async def isdefault(self):
|
||||
"""Is option has defaut value"""
|
||||
self._option_bag.option
|
||||
return self._values.is_default_owner(self._option_bag)
|
||||
await self._get_option()
|
||||
return await self._values.is_default_owner(self._option_bag)
|
||||
|
||||
def set(self, owner):
|
||||
async def set(self, owner):
|
||||
"""Get owner for a specified option"""
|
||||
self._option_bag.option
|
||||
await self._get_option()
|
||||
try:
|
||||
obj_owner = getattr(owners, owner)
|
||||
except AttributeError:
|
||||
owners.addowner(owner)
|
||||
obj_owner = getattr(owners, owner)
|
||||
self._values.setowner(obj_owner,
|
||||
self._option_bag)
|
||||
await self._values.setowner(obj_owner,
|
||||
self._option_bag)
|
||||
|
||||
|
||||
class TiramisuOptionProperty(CommonTiramisuOption):
|
||||
"""Manage option's property"""
|
||||
_allow_optiondescription = True
|
||||
_follower_need_index = False
|
||||
_validate_properties = False
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
subconfig: Union[KernelConfig, SubConfig],
|
||||
option_bag: OptionBag,
|
||||
config: Optional['SubConfig']) -> None:
|
||||
super().__init__(name,
|
||||
subconfig,
|
||||
option_bag)
|
||||
option_bag: OptionBag) -> None:
|
||||
super().__init__(option_bag)
|
||||
if option_bag and option_bag.config_bag:
|
||||
self._settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
|
||||
def get(self,
|
||||
async def get(self,
|
||||
only_raises=False):
|
||||
"""Get properties for an option"""
|
||||
await self._get_option()
|
||||
if not only_raises:
|
||||
return self._option_bag.properties
|
||||
# do not check cache properties/permissives which are not save (unrestraint, ...)
|
||||
return self._settings.calc_raises_properties(self._option_bag)
|
||||
return await self._settings.calc_raises_properties(self._option_bag)
|
||||
|
||||
def add(self, prop):
|
||||
async def add(self, prop):
|
||||
"""Add new property for an option"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
if prop in FORBIDDEN_SET_PROPERTIES:
|
||||
raise ConfigError(_('cannot add this property: "{0}"').format(
|
||||
' '.join(prop)))
|
||||
props = self._settings._p_.getproperties(self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
option.impl_getproperties())
|
||||
self._settings.setproperties(self._option_bag.path,
|
||||
props | {prop},
|
||||
self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
props = await self._settings._p_.getproperties(self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
option.impl_getproperties())
|
||||
await self._settings.setproperties(self._option_bag.path,
|
||||
props | {prop},
|
||||
self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
|
||||
def pop(self, prop):
|
||||
async def pop(self, prop):
|
||||
"""Remove new property for an option"""
|
||||
option = self._option_bag.option
|
||||
props = self._settings._p_.getproperties(self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
option.impl_getproperties())
|
||||
self._settings.setproperties(self._option_bag.path,
|
||||
props - {prop},
|
||||
self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
option = await self._get_option()
|
||||
props = await self._settings._p_.getproperties(self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
option.impl_getproperties())
|
||||
await self._settings.setproperties(self._option_bag.path,
|
||||
props - {prop},
|
||||
self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
|
||||
def reset(self):
|
||||
async def reset(self):
|
||||
"""Reset all personalised properties"""
|
||||
option = self._option_bag.option
|
||||
self._settings.reset(self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
await self._get_option()
|
||||
await self._settings.reset(self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
|
||||
|
||||
class TiramisuOptionPermissive(CommonTiramisuOption):
|
||||
@ -425,29 +393,27 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
|
||||
_follower_need_index = False
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
subconfig: Union[KernelConfig, SubConfig],
|
||||
option_bag: OptionBag,
|
||||
config: Optional['SubConfig']) -> None:
|
||||
super().__init__(name,
|
||||
subconfig,
|
||||
option_bag)
|
||||
option_bag: OptionBag) -> None:
|
||||
super().__init__(option_bag)
|
||||
if option_bag and option_bag.config_bag:
|
||||
self._settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get permissives value"""
|
||||
return self._settings.getpermissives(self._option_bag)
|
||||
await self._get_option()
|
||||
return await self._settings.getpermissives(self._option_bag)
|
||||
|
||||
def set(self, permissives):
|
||||
async def set(self, permissives):
|
||||
"""Set permissives value"""
|
||||
self._settings.setpermissives(self._option_bag,
|
||||
permissives=permissives)
|
||||
await self._get_option()
|
||||
await self._settings.setpermissives(self._option_bag,
|
||||
permissives=permissives)
|
||||
|
||||
def reset(self):
|
||||
async def reset(self):
|
||||
"""Reset all personalised permissive"""
|
||||
self._settings.reset_permissives(self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
await self._get_option()
|
||||
await self._settings.reset_permissives(self._option_bag,
|
||||
self._option_bag.config_bag.context)
|
||||
|
||||
|
||||
class TiramisuOptionInformation(CommonTiramisuOption):
|
||||
@ -455,88 +421,176 @@ class TiramisuOptionInformation(CommonTiramisuOption):
|
||||
_allow_optiondescription = True
|
||||
_follower_need_index = False
|
||||
|
||||
def get(self, key, default=undefined):
|
||||
def __init__(self,
|
||||
option_bag: OptionBag) -> None:
|
||||
super().__init__(option_bag)
|
||||
|
||||
async def get(self, key, default=undefined):
|
||||
"""Get information"""
|
||||
path = self._option_bag.path
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
try:
|
||||
return values.get_information(key, path=path)
|
||||
return await values.get_information(key,
|
||||
path=path)
|
||||
except ValueError:
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
return option.impl_get_information(key, default)
|
||||
|
||||
def set(self, key, value):
|
||||
async def set(self, key, value):
|
||||
"""Set information"""
|
||||
path = self._option_bag.path
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
values.set_information(key, value, path=path)
|
||||
await values.set_information(key, value, path=path)
|
||||
|
||||
def reset(self,
|
||||
async def reset(self,
|
||||
key):
|
||||
"""Remove information"""
|
||||
path = self._option_bag.path
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
values.del_information(key, path=path)
|
||||
await values.del_information(key,
|
||||
path=path)
|
||||
|
||||
def list(self):
|
||||
async def list(self):
|
||||
"""List information's keys"""
|
||||
await self._get_option()
|
||||
path = self._option_bag.path
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
return values.list_information(path)
|
||||
return await values.list_information(path)
|
||||
|
||||
async def len(self):
|
||||
"""Length of leadership"""
|
||||
option = await self._get_option()
|
||||
# for example if index is None
|
||||
if '_length' not in vars(self):
|
||||
self._length = self._subconfig.cfgimpl_get_length()
|
||||
return self._length
|
||||
|
||||
|
||||
class _TiramisuOptionValueOption:
|
||||
def get(self):
|
||||
def option_type(typ):
|
||||
if not isinstance(typ, list):
|
||||
types = [typ]
|
||||
else:
|
||||
types = typ
|
||||
|
||||
def wrapper(func):
|
||||
@wraps(func)
|
||||
async def wrapped(*args, **kwargs):
|
||||
for typ in types:
|
||||
if typ == 'group':
|
||||
if args[0]._option_bag.config_bag.context.impl_type == 'group':
|
||||
return await func(*args, **kwargs, is_group=True)
|
||||
else:
|
||||
option = await args[0]._get_option()
|
||||
if typ == 'option':
|
||||
if option.impl_is_optiondescription():
|
||||
raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
|
||||
elif typ == 'optiondescription':
|
||||
if not option.impl_is_optiondescription():
|
||||
raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
|
||||
elif typ == 'leader':
|
||||
if not option.impl_is_leader():
|
||||
raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
|
||||
elif typ == 'follower':
|
||||
if not option.impl_is_follower() and not option.impl_is_leader():
|
||||
raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
|
||||
elif typ == 'choice':
|
||||
if not isinstance(option, ChoiceOption):
|
||||
raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
|
||||
return await func(*args, **kwargs)
|
||||
return wrapped
|
||||
return wrapper
|
||||
|
||||
|
||||
class TiramisuOptionValue(CommonTiramisuOption):
|
||||
"""Manage option's value"""
|
||||
_allow_optiondescription = True
|
||||
_follower_need_index = True
|
||||
_validate_properties = True
|
||||
|
||||
@option_type('optiondescription')
|
||||
async def dict(self,
|
||||
flatten=False,
|
||||
withvalue=undefined,
|
||||
withoption=None,
|
||||
withwarning: bool=False,
|
||||
fullpath=False):
|
||||
"""Dict with path as key and value"""
|
||||
name = self._option_bag.option.impl_getname()
|
||||
subconfig = await self._subconfig.get_subconfig(self._option_bag)
|
||||
config_bag = self._option_bag.config_bag
|
||||
if not withwarning and config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
return await subconfig.make_dict(config_bag=config_bag,
|
||||
flatten=flatten,
|
||||
fullpath=fullpath,
|
||||
withoption=withoption,
|
||||
withvalue=withvalue)
|
||||
|
||||
@option_type('option')
|
||||
async def get(self):
|
||||
"""Get option's value"""
|
||||
option = self._option_bag.option
|
||||
self._test_follower_index()
|
||||
return self._subconfig.getattr(self._name,
|
||||
self._option_bag)
|
||||
if self._option_bag.option.impl_is_follower() and self._option_bag.index is None:
|
||||
raise APIError('index must be set with a follower option')
|
||||
return await self._subconfig.getattr(self._name,
|
||||
self._option_bag)
|
||||
|
||||
def set(self, value):
|
||||
@option_type('option')
|
||||
async def set(self, value):
|
||||
"""Change option's value"""
|
||||
option = self._option_bag.option
|
||||
self._test_follower_index()
|
||||
if self._option_bag.option.impl_is_follower() and \
|
||||
self._option_bag.index is None:
|
||||
raise APIError('index must be set with a follower option')
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
if isinstance(value, list):
|
||||
while undefined in value:
|
||||
idx = value.index(undefined)
|
||||
soption_bag = self._option_bag.copy()
|
||||
soption_bag.index = idx
|
||||
value[idx] = values.getdefaultvalue(soption_bag)
|
||||
value[idx] = await values.getdefaultvalue(soption_bag)
|
||||
elif value == undefined:
|
||||
value = values.getdefaultvalue(self._option_bag)
|
||||
self._subconfig.setattr(value,
|
||||
self._option_bag)
|
||||
value = await values.getdefaultvalue(self._option_bag)
|
||||
await self._subconfig.setattr(value,
|
||||
self._option_bag)
|
||||
|
||||
def reset(self):
|
||||
@option_type(['group', 'option'])
|
||||
async def reset(self,
|
||||
is_group: bool=False):
|
||||
"""Reset value for an option"""
|
||||
self._test_follower_index()
|
||||
self._subconfig.delattr(self._option_bag)
|
||||
if is_group:
|
||||
await self._option_bag.config_bag.context.reset(self._option_bag.path)
|
||||
else:
|
||||
if self._option_bag.option.impl_is_follower() and self._option_bag.index is None:
|
||||
raise APIError('index must be set with a follower option')
|
||||
await self._subconfig.delattr(self._option_bag)
|
||||
|
||||
def default(self):
|
||||
@option_type('option')
|
||||
async def default(self):
|
||||
"""Get default value (default of option or calculated value)"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
values = self._option_bag.config_bag.context.cfgimpl_get_values()
|
||||
if option.impl_is_follower() and self._option_bag.index is None:
|
||||
value = []
|
||||
length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
length = await self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
settings = self._option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
for idx in range(length):
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(option,
|
||||
self._option_bag.path,
|
||||
idx,
|
||||
self._option_bag.config_bag)
|
||||
value.append(values.getdefaultvalue(soption_bag))
|
||||
soption_bag.properties = await settings.getproperties(soption_bag)
|
||||
value.append(await values.getdefaultvalue(soption_bag))
|
||||
return value
|
||||
else:
|
||||
return values.getdefaultvalue(self._option_bag)
|
||||
return await values.getdefaultvalue(self._option_bag)
|
||||
|
||||
def valid(self):
|
||||
@option_type('option')
|
||||
async def valid(self):
|
||||
try:
|
||||
with catch_warnings(record=True) as warns:
|
||||
simplefilter("always", ValueErrorWarning)
|
||||
self.get()
|
||||
await self.get()
|
||||
for warn in warns:
|
||||
if isinstance(warns.message, ValueErrorWarning):
|
||||
return False
|
||||
@ -544,266 +598,179 @@ class _TiramisuOptionValueOption:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class _TiramisuOptionValueChoiceOption:
|
||||
def list(self):
|
||||
@option_type('choice')
|
||||
async def list(self):
|
||||
"""All values available for a ChoiceOption"""
|
||||
option = self._option_bag.option
|
||||
return option.impl_get_values(self._option_bag)
|
||||
option = await self._get_option()
|
||||
return await option.impl_get_values(self._option_bag)
|
||||
|
||||
|
||||
class _TiramisuOptionValueLeader:
|
||||
def pop(self, index):
|
||||
@option_type('leader')
|
||||
async def pop(self, index):
|
||||
"""Pop a value"""
|
||||
if self._option_bag.option.impl_is_follower() and self._option_bag.index is None:
|
||||
raise APIError('index must be set with a follower option')
|
||||
option_bag = self._option_bag
|
||||
assert not option_bag.option.impl_is_symlinkoption(), _("can't delete a SymLinkOption")
|
||||
option_bag.config_bag.context.cfgimpl_get_values().reset_leadership(index,
|
||||
option_bag,
|
||||
self._subconfig)
|
||||
await option_bag.config_bag.context.cfgimpl_get_values().reset_leadership(index,
|
||||
option_bag,
|
||||
self._subconfig)
|
||||
|
||||
def len(self):
|
||||
"""Length of leadership"""
|
||||
option = self._option_bag.option
|
||||
# for example if index is None
|
||||
if '_length' not in vars(self):
|
||||
self._length = self._subconfig.cfgimpl_get_length()
|
||||
return self._length
|
||||
|
||||
|
||||
class _TiramisuOptionValueFollower:
|
||||
def len(self):
|
||||
@option_type('follower')
|
||||
async def len(self):
|
||||
"""Length of follower option"""
|
||||
option = self._option_bag.option
|
||||
option = await self._get_option()
|
||||
# for example if index is None
|
||||
if '_length' not in vars(self):
|
||||
self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
self._length = await self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
|
||||
return self._length
|
||||
|
||||
|
||||
class _TiramisuOptionValueGroup:
|
||||
def reset(self):
|
||||
"""Reset value"""
|
||||
self._option_bag.config_bag.context.reset(self._option_bag.path)
|
||||
|
||||
|
||||
class _TiramisuOptionValueOptionDescription:
|
||||
|
||||
def dict(self,
|
||||
flatten=False,
|
||||
withvalue=undefined,
|
||||
withoption=None,
|
||||
withwarning: bool=False,
|
||||
fullpath=False):
|
||||
"""Dict with path as key and value"""
|
||||
self._get_option()
|
||||
name = self._option_bag.option.impl_getname()
|
||||
subconfig = self._subconfig.get_subconfig(self._option_bag)
|
||||
config_bag = self._option_bag.config_bag
|
||||
if not withwarning and config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
return subconfig.make_dict(config_bag=config_bag,
|
||||
flatten=flatten,
|
||||
fullpath=fullpath,
|
||||
withoption=withoption,
|
||||
withvalue=withvalue)
|
||||
|
||||
|
||||
class TiramisuOptionValue(CommonTiramisuOption):
|
||||
"""Manage option's value"""
|
||||
_allow_optiondescription = True
|
||||
_follower_need_index = False
|
||||
|
||||
def __new__(cls,
|
||||
name,
|
||||
subconfig,
|
||||
option_bag,
|
||||
config):
|
||||
types = [CommonTiramisuOption]
|
||||
if option_bag.option and option_bag.option.impl_is_optiondescription():
|
||||
types.append(_TiramisuOptionValueOptionDescription)
|
||||
elif subconfig is not None:
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
option_bag.config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
types.append(_TiramisuOptionValueOption)
|
||||
if isinstance(option, ChoiceOption):
|
||||
types.append(_TiramisuOptionValueChoiceOption)
|
||||
if option.impl_is_leader():
|
||||
types.append(_TiramisuOptionValueLeader)
|
||||
elif option.impl_is_follower():
|
||||
types.append(_TiramisuOptionValueFollower)
|
||||
if option_bag.config_bag.context.impl_type == 'group':
|
||||
types.append(_TiramisuOptionValueGroup)
|
||||
new_type_dict = {'_allow_optiondescription': cls._allow_optiondescription,
|
||||
'_follower_need_index': cls._follower_need_index}
|
||||
if option_bag.option and option_bag.option.impl_is_optiondescription():
|
||||
new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name,
|
||||
subconfig=subconfig,
|
||||
option_bag=option_bag,
|
||||
config=config)
|
||||
else:
|
||||
new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name,
|
||||
subconfig=subconfig,
|
||||
option_bag=option_bag)
|
||||
new_type.__doc__ = cls.__doc__
|
||||
return new_type
|
||||
|
||||
|
||||
def _registers(_registers: Dict[str, type],
|
||||
prefix: str,
|
||||
extra_type: Optional[type]=None) -> None:
|
||||
extra_type: Optional[type]=None):
|
||||
for module_name in globals().keys():
|
||||
if module_name != prefix and module_name.startswith(prefix):
|
||||
if module_name != prefix and module_name.startswith(prefix): # and \
|
||||
module = globals()[module_name]
|
||||
func_name = module_name[len(prefix):].lower()
|
||||
_registers[func_name] = module
|
||||
|
||||
|
||||
class _TiramisuOption(CommonTiramisu):
|
||||
"""Manage selected option"""
|
||||
_validate_properties = False
|
||||
_registers = {}
|
||||
def __init__(self,
|
||||
name: Optional[str],
|
||||
path: Optional[str]=None,
|
||||
index: Optional[int]=None,
|
||||
subconfig: Union[None, KernelConfig, SubConfig]=None,
|
||||
config_bag: Optional[ConfigBag]=None) -> None:
|
||||
self._name = name
|
||||
self._subconfig = subconfig
|
||||
self._path = path
|
||||
self._index = index
|
||||
self._config_bag = config_bag
|
||||
self._option_bag = OptionBag()
|
||||
self._option_bag.path = self._path
|
||||
self._option_bag.index = self._index
|
||||
self._option_bag.config_bag = self._config_bag
|
||||
self._tiramisu_dict = None
|
||||
self._config = None
|
||||
if not self._registers:
|
||||
_registers(self._registers, 'TiramisuOption')
|
||||
|
||||
def _get_config(self):
|
||||
if self._config is None and self._subconfig is not None:
|
||||
self._config = self._subconfig.get_subconfig(self._option_bag)
|
||||
return self._config
|
||||
|
||||
def __getattr__(self, subfunc: str) -> Any:
|
||||
if subfunc in self._registers:
|
||||
subconfig = self._subconfig
|
||||
if subconfig:
|
||||
option = self._get_option()
|
||||
if option.impl_is_optiondescription() and subfunc == 'option':
|
||||
config = self._get_config()
|
||||
else:
|
||||
config = None
|
||||
else:
|
||||
config = None
|
||||
return self._registers[subfunc](self._name,
|
||||
subconfig,
|
||||
self._option_bag,
|
||||
config)
|
||||
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) # pragma: no cover
|
||||
#__________________________________________________________________________________________________
|
||||
#
|
||||
|
||||
|
||||
class TiramisuConfig(TiramisuHelp):
|
||||
def __init__(self,
|
||||
config_bag: Optional[ConfigBag]) -> None:
|
||||
config_bag: ConfigBag,
|
||||
orig_config_bags: Optional[List[OptionBag]]) -> None:
|
||||
self._config_bag = config_bag
|
||||
self._orig_config_bags = orig_config_bags
|
||||
|
||||
def _return_config(self,
|
||||
async def _return_config(self,
|
||||
config):
|
||||
if isinstance(config, KernelConfig):
|
||||
return Config(config)
|
||||
return await Config(config)
|
||||
if isinstance(config, KernelMetaConfig):
|
||||
return MetaConfig(config)
|
||||
return await MetaConfig(config)
|
||||
if isinstance(config, KernelMixConfig):
|
||||
return MixConfig([], config)
|
||||
return await MixConfig([], config)
|
||||
if isinstance(config, KernelGroupConfig):
|
||||
return GroupConfig(config)
|
||||
return await GroupConfig(config)
|
||||
raise Exception(_('unknown config type {}').format(type(config)))
|
||||
|
||||
async def _reset_config_properties(self):
|
||||
config = self._config_bag.context
|
||||
settings = config.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(config._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
self._config_bag.properties = properties
|
||||
self._config_bag.permissives = permissives
|
||||
if self._orig_config_bags:
|
||||
for config_bag in self._orig_config_bags:
|
||||
config_bag.properties = properties
|
||||
config_bag.permissives = permissives
|
||||
|
||||
class _TiramisuOptionDescription(_TiramisuOption, TiramisuConfig):
|
||||
def find(self,
|
||||
name: str,
|
||||
value=undefined,
|
||||
type=None,
|
||||
first: bool=False):
|
||||
|
||||
class TiramisuOption(CommonTiramisu, TiramisuConfig):
|
||||
"""Manage selected option"""
|
||||
_validate_properties = False
|
||||
_registers = {}
|
||||
def __init__(self,
|
||||
path: Optional[str]=None,
|
||||
index: Optional[int]=None,
|
||||
config_bag: Optional[ConfigBag]=None) -> None:
|
||||
self._option_bag = OptionBag()
|
||||
self._option_bag.config_bag = config_bag
|
||||
self._option_bag.path = path
|
||||
self._option_bag.index = index
|
||||
self._subconfig = None
|
||||
self._tiramisu_dict = None
|
||||
if not self._registers:
|
||||
_registers(self._registers, 'TiramisuOption')
|
||||
|
||||
def __getattr__(self, subfunc: str) -> Any:
|
||||
if subfunc in self._registers:
|
||||
return self._registers[subfunc](self._option_bag)
|
||||
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) # pragma: no cover
|
||||
|
||||
@option_type('optiondescription')
|
||||
async def find(self,
|
||||
name: str,
|
||||
value=undefined,
|
||||
type=None,
|
||||
first: bool=False):
|
||||
"""find an option by name (only for optiondescription)"""
|
||||
if not first:
|
||||
ret = []
|
||||
option = self._get_option()
|
||||
option = await self._get_option()
|
||||
config_bag = self._option_bag.config_bag
|
||||
oname = option.impl_getname()
|
||||
path = self._subconfig._get_subpath(oname)
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
None,
|
||||
self._config_bag)
|
||||
subconfig = self._subconfig.get_subconfig(option_bag)
|
||||
for path in subconfig.find(byname=name,
|
||||
byvalue=value,
|
||||
bytype=type,
|
||||
_subpath=self._path,
|
||||
config_bag=self._config_bag):
|
||||
subconfig, name = self._config_bag.context.cfgimpl_get_home_by_path(path,
|
||||
self._config_bag)
|
||||
t_option = TiramisuOption(name,
|
||||
path,
|
||||
config_bag)
|
||||
subconfig = await self._subconfig.get_subconfig(option_bag)
|
||||
async for path in subconfig.find(byname=name,
|
||||
byvalue=value,
|
||||
bytype=type,
|
||||
_subpath=option_bag.path,
|
||||
config_bag=config_bag):
|
||||
t_option = TiramisuOption(path,
|
||||
None, # index for a follower ?
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
config_bag)
|
||||
if first:
|
||||
return t_option
|
||||
ret.append(t_option)
|
||||
return ret
|
||||
|
||||
def group_type(self):
|
||||
@option_type('optiondescription')
|
||||
async def group_type(self):
|
||||
"""Get type for an optiondescription (only for optiondescription)"""
|
||||
return self._get_option().impl_get_group_type()
|
||||
option = await self._get_option()
|
||||
return option.impl_get_group_type()
|
||||
|
||||
def _filter(self,
|
||||
opt,
|
||||
subconfig,
|
||||
config_bag):
|
||||
async def _filter(self,
|
||||
opt,
|
||||
subconfig,
|
||||
config_bag):
|
||||
settings = config_bag.context.cfgimpl_get_settings()
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(opt,
|
||||
opt.impl_getpath(),
|
||||
None,
|
||||
config_bag)
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
if opt.impl_is_optiondescription():
|
||||
config_bag.context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
return subconfig.get_subconfig(option_bag)
|
||||
subconfig.getattr(opt.impl_getname(),
|
||||
option_bag)
|
||||
await settings.validate_properties(option_bag)
|
||||
return await subconfig.get_subconfig(option_bag)
|
||||
await subconfig.getattr(opt.impl_getname(),
|
||||
option_bag)
|
||||
|
||||
def list(self,
|
||||
type='option',
|
||||
group_type=None):
|
||||
@option_type('optiondescription')
|
||||
async def list(self,
|
||||
type='option',
|
||||
group_type=None):
|
||||
"""List options (by default list only option)"""
|
||||
assert type in ('all', 'option', 'optiondescription'), _('unknown list type {}').format(type)
|
||||
assert group_type is None or isinstance(group_type, groups.GroupType), \
|
||||
_("unknown group_type: {0}").format(group_type)
|
||||
config_bag = self._config_bag
|
||||
config_bag = self._option_bag.config_bag
|
||||
if config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
option = self._get_option()
|
||||
option = await self._get_option()
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
option.impl_getpath(),
|
||||
None,
|
||||
config_bag)
|
||||
subconfig = self._subconfig.get_subconfig(option_bag)
|
||||
for opt in option.get_children(config_bag):
|
||||
subconfig = await self._subconfig.get_subconfig(option_bag)
|
||||
options = []
|
||||
for opt in await option.get_children(config_bag):
|
||||
try:
|
||||
self._filter(opt,
|
||||
subconfig,
|
||||
config_bag)
|
||||
await self._filter(opt,
|
||||
subconfig,
|
||||
config_bag)
|
||||
except PropertiesOptionError:
|
||||
continue
|
||||
if opt.impl_is_optiondescription():
|
||||
@ -812,106 +779,78 @@ class _TiramisuOptionDescription(_TiramisuOption, TiramisuConfig):
|
||||
continue
|
||||
elif type == 'optiondescription':
|
||||
continue
|
||||
name = opt.impl_getname()
|
||||
path = opt.impl_getpath()
|
||||
yield TiramisuOption(name,
|
||||
path,
|
||||
None,
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
options.append(TiramisuOption(opt.impl_getpath(),
|
||||
None,
|
||||
self._option_bag.config_bag))
|
||||
return options
|
||||
|
||||
def _load_dict(self,
|
||||
clearable: str="all",
|
||||
remotable: str="minimum"):
|
||||
root = self._get_option().impl_getpath()
|
||||
self._tiramisu_dict = TiramisuDict(self._return_config(self._config_bag.context),
|
||||
async def _load_dict(self,
|
||||
clearable: str="all",
|
||||
remotable: str="minimum"):
|
||||
option = await self._get_option()
|
||||
root = option.impl_getpath()
|
||||
self._tiramisu_dict = TiramisuDict(await self._return_config(self._option_bag.config_bag.context),
|
||||
root=root,
|
||||
clearable=clearable,
|
||||
remotable=remotable)
|
||||
|
||||
def dict(self,
|
||||
@option_type('optiondescription')
|
||||
async def dict(self,
|
||||
clearable: str="all",
|
||||
remotable: str="minimum",
|
||||
form: List=[],
|
||||
force: bool=False) -> Dict:
|
||||
"""convert config and option to tiramisu format"""
|
||||
if force or self._tiramisu_dict is None:
|
||||
self._load_dict(clearable, remotable)
|
||||
return self._tiramisu_dict.todict(form)
|
||||
await self._load_dict(clearable, remotable)
|
||||
return await self._tiramisu_dict.todict(form)
|
||||
|
||||
def updates(self,
|
||||
body: List) -> Dict:
|
||||
@option_type('optiondescription')
|
||||
async def updates(self,
|
||||
body: List) -> Dict:
|
||||
"""updates value with tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
self._load_dict()
|
||||
return self._tiramisu_dict.set_updates(body)
|
||||
|
||||
|
||||
class TiramisuOption(CommonTiramisuOption):
|
||||
"""Manage selected option"""
|
||||
def __new__(cls,
|
||||
name: Optional[str],
|
||||
path: Optional[str]=None,
|
||||
index: Optional[int]=None,
|
||||
subconfig: Union[None, KernelConfig, SubConfig]=None,
|
||||
config_bag: Optional[ConfigBag]=None) -> None:
|
||||
if subconfig:
|
||||
# not for groupconfig
|
||||
if '.' in name:
|
||||
subconfig, name = config_bag.context.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
if option.impl_is_optiondescription():
|
||||
return _TiramisuOptionDescription(name=name,
|
||||
path=path,
|
||||
index=index,
|
||||
subconfig=subconfig,
|
||||
config_bag=config_bag)
|
||||
return _TiramisuOption(name=name,
|
||||
path=path,
|
||||
index=index,
|
||||
subconfig=subconfig,
|
||||
config_bag=config_bag)
|
||||
|
||||
|
||||
await self._load_dict()
|
||||
return await self._tiramisu_dict.set_updates(body)
|
||||
|
||||
|
||||
class TiramisuContextInformation(TiramisuConfig):
|
||||
"""Manage config informations"""
|
||||
def get(self, name, default=undefined):
|
||||
async def get(self, name, default=undefined):
|
||||
"""Get an information"""
|
||||
return self._config_bag.context.impl_get_information(name, default)
|
||||
return await self._config_bag.context.impl_get_information(name, default)
|
||||
|
||||
def set(self, name, value):
|
||||
async def set(self, name, value):
|
||||
"""Set an information"""
|
||||
self._config_bag.context.impl_set_information(name, value)
|
||||
await self._config_bag.context.impl_set_information(name, value)
|
||||
|
||||
def reset(self, name):
|
||||
async def reset(self, name):
|
||||
"""Remove an information"""
|
||||
self._config_bag.context.impl_del_information(name)
|
||||
await self._config_bag.context.impl_del_information(name)
|
||||
|
||||
def list(self):
|
||||
async def list(self):
|
||||
"""List information's keys"""
|
||||
return self._config_bag.context.impl_list_information()
|
||||
return await self._config_bag.context.impl_list_information()
|
||||
|
||||
|
||||
class TiramisuContextValue(TiramisuConfig):
|
||||
"""Manage config value"""
|
||||
def mandatory(self):
|
||||
async def mandatory(self):
|
||||
"""Return path of options with mandatory property without any value"""
|
||||
return self._config_bag.context.cfgimpl_get_values().mandatory_warnings(self._config_bag)
|
||||
options = []
|
||||
async for option in self._config_bag.context.cfgimpl_get_values().mandatory_warnings(self._config_bag):
|
||||
options.append(option)
|
||||
return options
|
||||
|
||||
# FIXME should be only for group/meta
|
||||
def set(self,
|
||||
path: str,
|
||||
value,
|
||||
index=None,
|
||||
only_config=undefined,
|
||||
force_default=undefined,
|
||||
force_default_if_same=undefined,
|
||||
force_dont_change_value=undefined):
|
||||
async def set(self,
|
||||
path: str,
|
||||
value,
|
||||
index=None,
|
||||
only_config=undefined,
|
||||
force_default=undefined,
|
||||
force_default_if_same=undefined,
|
||||
force_dont_change_value=undefined):
|
||||
"""Set a value in config or children for a path"""
|
||||
kwargs = {}
|
||||
if only_config is not undefined:
|
||||
@ -922,22 +861,22 @@ class TiramisuContextValue(TiramisuConfig):
|
||||
kwargs['force_default_if_same'] = force_default_if_same
|
||||
if force_dont_change_value is not undefined:
|
||||
kwargs['force_dont_change_value'] = force_dont_change_value
|
||||
return self._config_bag.context.set_value(path,
|
||||
index,
|
||||
value,
|
||||
self._config_bag,
|
||||
**kwargs)
|
||||
return await self._config_bag.context.set_value(path,
|
||||
index,
|
||||
value,
|
||||
self._config_bag,
|
||||
**kwargs)
|
||||
|
||||
# FIXME should be only for group/meta
|
||||
def reset(self,
|
||||
async def reset(self,
|
||||
path: str,
|
||||
only_children: bool=False):
|
||||
"""Reset value"""
|
||||
self._config_bag.context.reset(path,
|
||||
only_children,
|
||||
self._config_bag)
|
||||
await self._config_bag.context.reset(path,
|
||||
only_children,
|
||||
self._config_bag)
|
||||
|
||||
def dict(self,
|
||||
async def dict(self,
|
||||
flatten=False,
|
||||
withvalue=undefined,
|
||||
withoption=None,
|
||||
@ -945,19 +884,19 @@ class TiramisuContextValue(TiramisuConfig):
|
||||
fullpath=False):
|
||||
"""Dict with path as key and value"""
|
||||
config_bag = self._config_bag
|
||||
if not withwarning and config_bag.properties and 'warnings' in config_bag.properties:
|
||||
if not withwarning and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
return config_bag.context.make_dict(config_bag,
|
||||
flatten=flatten,
|
||||
fullpath=fullpath,
|
||||
withoption=withoption,
|
||||
withvalue=withvalue)
|
||||
return await config_bag.context.make_dict(config_bag,
|
||||
flatten=flatten,
|
||||
fullpath=fullpath,
|
||||
withoption=withoption,
|
||||
withvalue=withvalue)
|
||||
|
||||
def exportation(self,
|
||||
with_default_owner: bool=False):
|
||||
async def exportation(self,
|
||||
with_default_owner: bool=False):
|
||||
"""Export all values"""
|
||||
exportation = self._config_bag.context.cfgimpl_get_values()._p_.exportation()
|
||||
exportation = await self._config_bag.context.cfgimpl_get_values()._p_.exportation()
|
||||
if not with_default_owner:
|
||||
exportation = [list(exportation[0]), list(exportation[1]), list(exportation[2]), list(exportation[3])]
|
||||
index = exportation[0].index(None)
|
||||
@ -967,123 +906,123 @@ class TiramisuContextValue(TiramisuConfig):
|
||||
exportation[3].pop(index)
|
||||
return exportation
|
||||
|
||||
def importation(self, values):
|
||||
async def importation(self, values):
|
||||
"""Import values"""
|
||||
if None not in values[0]:
|
||||
context_owner = self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
context_owner = await self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
else:
|
||||
context_owner = None
|
||||
self._config_bag.context.cfgimpl_get_values()._p_.importation(values)
|
||||
self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
await self._config_bag.context.cfgimpl_get_values()._p_.importation(values)
|
||||
await self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
if context_owner is not None:
|
||||
self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
|
||||
None,
|
||||
context_owner,
|
||||
None,
|
||||
True)
|
||||
await self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
|
||||
None,
|
||||
context_owner,
|
||||
None,
|
||||
True)
|
||||
|
||||
|
||||
class TiramisuContextOwner(TiramisuConfig):
|
||||
"""Global owner"""
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get owner"""
|
||||
return self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
return await self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
|
||||
def set(self, owner):
|
||||
async def set(self, owner):
|
||||
"""Set owner"""
|
||||
try:
|
||||
obj_owner = getattr(owners, owner)
|
||||
except AttributeError:
|
||||
owners.addowner(owner)
|
||||
obj_owner = getattr(owners, owner)
|
||||
self._config_bag.context.cfgimpl_get_values().set_context_owner(obj_owner)
|
||||
await self._config_bag.context.cfgimpl_get_values().set_context_owner(obj_owner)
|
||||
|
||||
|
||||
class TiramisuContextProperty(TiramisuConfig):
|
||||
"""Manage config properties"""
|
||||
|
||||
def read_only(self):
|
||||
async def read_only(self):
|
||||
"""Set config to read only mode"""
|
||||
old_props = self._config_bag.properties
|
||||
settings = self._config_bag.context.cfgimpl_get_settings()
|
||||
settings.read_only(self._config_bag.context)
|
||||
del self._config_bag.properties
|
||||
await settings.read_only(self._config_bag.context)
|
||||
await self._reset_config_properties()
|
||||
if 'force_store_value' not in old_props and \
|
||||
'force_store_value' in self._config_bag.properties:
|
||||
self._force_store_value()
|
||||
await self._force_store_value()
|
||||
|
||||
def read_write(self):
|
||||
async def read_write(self):
|
||||
"""Set config to read and write mode"""
|
||||
old_props = self._config_bag.properties
|
||||
settings = self._config_bag.context.cfgimpl_get_settings()
|
||||
settings.read_write(self._config_bag.context)
|
||||
await settings.read_write(self._config_bag.context)
|
||||
or_properties = settings.rw_append - settings.ro_append - SPECIAL_PROPERTIES
|
||||
permissives = frozenset(settings.get_context_permissives() | or_properties)
|
||||
settings.set_context_permissives(permissives)
|
||||
del self._config_bag.properties
|
||||
permissives = frozenset(await settings.get_context_permissives() | or_properties)
|
||||
await settings.set_context_permissives(permissives)
|
||||
await self._reset_config_properties()
|
||||
if 'force_store_value' not in old_props and \
|
||||
'force_store_value' in self._config_bag.properties:
|
||||
self._force_store_value()
|
||||
await self._force_store_value()
|
||||
|
||||
def add(self, prop):
|
||||
async def add(self, prop):
|
||||
"""Add a config property"""
|
||||
props = set(self.get())
|
||||
props = set(await self.get())
|
||||
props.add(prop)
|
||||
self._set(frozenset(props))
|
||||
await self._set(frozenset(props))
|
||||
|
||||
def pop(self, prop):
|
||||
async def pop(self, prop):
|
||||
"""Remove a config property"""
|
||||
props = set(self.get())
|
||||
props = set(await self.get())
|
||||
if prop in props:
|
||||
props.remove(prop)
|
||||
self._set(frozenset(props))
|
||||
await self._set(frozenset(props))
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get all config properties"""
|
||||
return self._config_bag.properties
|
||||
|
||||
def _set(self, props):
|
||||
async def _set(self, props):
|
||||
"""Personalise config properties"""
|
||||
if 'force_store_value' in props:
|
||||
force_store_value = 'force_store_value' not in self._config_bag.properties
|
||||
else:
|
||||
force_store_value = False
|
||||
context = self._config_bag.context
|
||||
context.cfgimpl_get_settings().set_context_properties(props,
|
||||
context)
|
||||
del self._config_bag.properties
|
||||
await context.cfgimpl_get_settings().set_context_properties(props,
|
||||
context)
|
||||
await self._reset_config_properties()
|
||||
if force_store_value:
|
||||
self._force_store_value()
|
||||
await self._force_store_value()
|
||||
|
||||
def reset(self):
|
||||
async def reset(self):
|
||||
"""Remove config properties"""
|
||||
context = self._config_bag.context
|
||||
context.cfgimpl_get_settings().reset(None,
|
||||
context)
|
||||
del self._config_bag.properties
|
||||
await context.cfgimpl_get_settings().reset(None,
|
||||
context)
|
||||
await self._reset_config_properties()
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""Export config properties"""
|
||||
return self._config_bag.context.cfgimpl_get_settings()._p_.exportation()
|
||||
return await self._config_bag.context.cfgimpl_get_settings()._p_.exportation()
|
||||
|
||||
def importation(self, properties):
|
||||
async def importation(self, properties):
|
||||
"""Import config properties"""
|
||||
if 'force_store_value' in properties.get(None, {}).get(None, []):
|
||||
force_store_value = 'force_store_value' not in self._config_bag.properties
|
||||
else:
|
||||
force_store_value = False
|
||||
self._config_bag.context.cfgimpl_get_settings()._p_.importation(properties)
|
||||
self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
del self._config_bag.properties
|
||||
await self._config_bag.context.cfgimpl_get_settings()._p_.importation(properties)
|
||||
await self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
await self._reset_config_properties()
|
||||
if force_store_value:
|
||||
self._force_store_value()
|
||||
await self._force_store_value()
|
||||
|
||||
def _force_store_value(self):
|
||||
async def _force_store_value(self):
|
||||
descr = self._config_bag.context.cfgimpl_get_description()
|
||||
descr.impl_build_force_store_values(self._config_bag)
|
||||
await descr.impl_build_force_store_values(self._config_bag)
|
||||
|
||||
def setdefault(self,
|
||||
async def setdefault(self,
|
||||
properties: Set[str],
|
||||
type: Optional[str]=None,
|
||||
when: Optional[str]=None) -> None:
|
||||
@ -1108,9 +1047,9 @@ class TiramisuContextProperty(TiramisuConfig):
|
||||
else:
|
||||
raise ValueError(_('unknown type {}').format(type))
|
||||
|
||||
def getdefault(self,
|
||||
type: Optional[str]=None,
|
||||
when: Optional[str]=None) -> Set[str]:
|
||||
async def getdefault(self,
|
||||
type: Optional[str]=None,
|
||||
when: Optional[str]=None) -> Set[str]:
|
||||
setting = self._config_bag.context.cfgimpl_get_settings()
|
||||
if type is None and when is None:
|
||||
return setting.default_properties
|
||||
@ -1134,45 +1073,45 @@ class TiramisuContextProperty(TiramisuConfig):
|
||||
class TiramisuContextPermissive(TiramisuConfig):
|
||||
"""Manage config permissives"""
|
||||
|
||||
def get(self):
|
||||
async def get(self):
|
||||
"""Get config permissives"""
|
||||
return self._config_bag.context.cfgimpl_get_settings().get_context_permissives()
|
||||
return await self._config_bag.context.cfgimpl_get_settings().get_context_permissives()
|
||||
|
||||
def _set(self, permissives):
|
||||
async def _set(self, permissives):
|
||||
"""Set config permissives"""
|
||||
self._config_bag.context.cfgimpl_get_settings().set_context_permissives(permissives)
|
||||
del self._config_bag.permissives
|
||||
await self._config_bag.context.cfgimpl_get_settings().set_context_permissives(permissives)
|
||||
await self._reset_config_properties()
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""Export config permissives"""
|
||||
return self._config_bag.context.cfgimpl_get_settings()._pp_.exportation()
|
||||
return await self._config_bag.context.cfgimpl_get_settings()._pp_.exportation()
|
||||
|
||||
def importation(self, permissives):
|
||||
async def importation(self, permissives):
|
||||
"""Import config permissives"""
|
||||
self._config_bag.context.cfgimpl_get_settings()._pp_.importation(permissives)
|
||||
self._config_bag.context.cfgimpl_reset_cache(None,
|
||||
None)
|
||||
del self._config_bag.permissives
|
||||
await self._config_bag.context.cfgimpl_get_settings()._pp_.importation(permissives)
|
||||
await self._config_bag.context.cfgimpl_reset_cache(None,
|
||||
None)
|
||||
await self._reset_config_properties()
|
||||
|
||||
def reset(self):
|
||||
async def reset(self):
|
||||
"""Remove config permissives"""
|
||||
context = self._config_bag.context
|
||||
context.cfgimpl_get_settings().reset_permissives(None,
|
||||
context)
|
||||
del self._config_bag.properties
|
||||
await context.cfgimpl_get_settings().reset_permissives(None,
|
||||
context)
|
||||
await self._reset_config_properties()
|
||||
|
||||
def add(self, prop):
|
||||
async def add(self, prop):
|
||||
"""Add a config permissive"""
|
||||
props = set(self.get())
|
||||
props = set(await self.get())
|
||||
props.add(prop)
|
||||
self._set(frozenset(props))
|
||||
await self._set(frozenset(props))
|
||||
|
||||
def pop(self, prop):
|
||||
async def pop(self, prop):
|
||||
"""Remove a config permissive"""
|
||||
props = set(self.get())
|
||||
props = set(await self.get())
|
||||
if prop in props:
|
||||
props.remove(prop)
|
||||
self._set(frozenset(props))
|
||||
await self._set(frozenset(props))
|
||||
|
||||
|
||||
class TiramisuContextOption(TiramisuConfig):
|
||||
@ -1182,83 +1121,76 @@ class TiramisuContextOption(TiramisuConfig):
|
||||
self._tiramisu_dict = None
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _find(self,
|
||||
name,
|
||||
value,
|
||||
type):
|
||||
for path in self._config_bag.context.find(byname=name,
|
||||
byvalue=value,
|
||||
bytype=type,
|
||||
config_bag=self._config_bag):
|
||||
subconfig, name = self._config_bag.context.cfgimpl_get_home_by_path(path,
|
||||
self._config_bag)
|
||||
yield TiramisuOption(name,
|
||||
path,
|
||||
None,
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
|
||||
def find(self,
|
||||
async def find(self,
|
||||
name,
|
||||
value=undefined,
|
||||
type=None,
|
||||
first=False):
|
||||
"""Find an or a list of options"""
|
||||
if first:
|
||||
return next(self._find(name, value, type))
|
||||
return self._find(name, value, type)
|
||||
options = []
|
||||
async for path in self._config_bag.context.find(byname=name,
|
||||
byvalue=value,
|
||||
bytype=type,
|
||||
config_bag=self._config_bag):
|
||||
option = TiramisuOption(path,
|
||||
None,
|
||||
self._config_bag)
|
||||
if first:
|
||||
return option
|
||||
options.append(option)
|
||||
return options
|
||||
|
||||
def _filter(self,
|
||||
opt,
|
||||
subconfig,
|
||||
config_bag):
|
||||
async def _filter(self,
|
||||
opt,
|
||||
subconfig,
|
||||
config_bag):
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(opt,
|
||||
opt.impl_getpath(),
|
||||
None,
|
||||
config_bag)
|
||||
settings = config_bag.context.cfgimpl_get_settings()
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
if opt.impl_is_optiondescription():
|
||||
config_bag.context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
return subconfig.get_subconfig(option_bag)
|
||||
subconfig.getattr(opt.impl_getname(),
|
||||
option_bag)
|
||||
await settings.validate_properties(option_bag)
|
||||
return await subconfig.get_subconfig(option_bag)
|
||||
await subconfig.getattr(opt.impl_getname(),
|
||||
option_bag)
|
||||
|
||||
def _walk(self,
|
||||
async def _walk(self,
|
||||
option,
|
||||
recursive,
|
||||
type_,
|
||||
group_type,
|
||||
config_bag,
|
||||
subconfig):
|
||||
for opt in option.get_children(config_bag):
|
||||
options = []
|
||||
for opt in await option.get_children(config_bag):
|
||||
try:
|
||||
subsubconfig = self._filter(opt,
|
||||
subconfig,
|
||||
config_bag)
|
||||
subsubconfig = await self._filter(opt,
|
||||
subconfig,
|
||||
config_bag)
|
||||
except PropertiesOptionError:
|
||||
continue
|
||||
if opt.impl_is_optiondescription():
|
||||
if recursive:
|
||||
yield from self._walk(opt,
|
||||
recursive,
|
||||
type_,
|
||||
group_type,
|
||||
config_bag,
|
||||
subsubconfig)
|
||||
options.extend(await self._walk(opt,
|
||||
recursive,
|
||||
type_,
|
||||
group_type,
|
||||
config_bag,
|
||||
subsubconfig))
|
||||
if type_ == 'option' or (type_ == 'optiondescription' and \
|
||||
group_type and opt.impl_get_group_type() != group_type):
|
||||
continue
|
||||
elif type_ == 'optiondescription':
|
||||
continue
|
||||
name = opt.impl_getname()
|
||||
path = opt.impl_getpath()
|
||||
yield TiramisuOption(name,
|
||||
path,
|
||||
None,
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
options.append(TiramisuOption(opt.impl_getpath(),
|
||||
None,
|
||||
self._config_bag))
|
||||
return options
|
||||
|
||||
def list(self,
|
||||
async def list(self,
|
||||
type='option',
|
||||
group_type=None,
|
||||
recursive=False):
|
||||
@ -1271,234 +1203,254 @@ class TiramisuContextOption(TiramisuConfig):
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
option = config_bag.context.cfgimpl_get_description()
|
||||
yield from self._walk(option,
|
||||
recursive,
|
||||
type,
|
||||
group_type,
|
||||
config_bag,
|
||||
config_bag.context)
|
||||
options = []
|
||||
for opt in await self._walk(option,
|
||||
recursive,
|
||||
type,
|
||||
group_type,
|
||||
config_bag,
|
||||
config_bag.context):
|
||||
options.append(opt)
|
||||
return options
|
||||
|
||||
def _load_dict(self,
|
||||
clearable="all",
|
||||
remotable="minimum"):
|
||||
self._tiramisu_dict = TiramisuDict(self._return_config(self._config_bag.context),
|
||||
async def _load_dict(self,
|
||||
clearable="all",
|
||||
remotable="minimum"):
|
||||
self._tiramisu_dict = TiramisuDict(await self._return_config(self._config_bag.context),
|
||||
root=None,
|
||||
clearable=clearable,
|
||||
remotable=remotable)
|
||||
|
||||
def dict(self,
|
||||
clearable="all",
|
||||
remotable="minimum",
|
||||
form=[],
|
||||
force=False):
|
||||
async def dict(self,
|
||||
clearable="all",
|
||||
remotable="minimum",
|
||||
form=[],
|
||||
force=False):
|
||||
"""convert config and option to tiramisu format"""
|
||||
if force or self._tiramisu_dict is None:
|
||||
self._load_dict(clearable, remotable)
|
||||
return self._tiramisu_dict.todict(form)
|
||||
await self._load_dict(clearable, remotable)
|
||||
return await self._tiramisu_dict.todict(form)
|
||||
|
||||
def updates(self,
|
||||
body: List) -> Dict:
|
||||
async def updates(self,
|
||||
body: List) -> Dict:
|
||||
"""updates value with tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
self._load_dict()
|
||||
return self._tiramisu_dict.set_updates(body)
|
||||
await self._load_dict()
|
||||
return await self._tiramisu_dict.set_updates(body)
|
||||
|
||||
|
||||
class _TiramisuContextConfigReset():
|
||||
def reset(self):
|
||||
async def reset(self):
|
||||
"""Remove all datas to current config (informations, values, properties, ...)"""
|
||||
# Option's values
|
||||
context_owner = self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
self._config_bag.context.cfgimpl_get_values()._p_.importation(([], [], [], []))
|
||||
self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
|
||||
None,
|
||||
context_owner,
|
||||
None,
|
||||
True)
|
||||
context_owner = await self._config_bag.context.cfgimpl_get_values().get_context_owner()
|
||||
await self._config_bag.context.cfgimpl_get_values()._p_.importation(([], [], [], []))
|
||||
await self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
|
||||
None,
|
||||
context_owner,
|
||||
None,
|
||||
True)
|
||||
# Option's informations
|
||||
self._config_bag.context.cfgimpl_get_values()._p_.del_informations()
|
||||
await self._config_bag.context.cfgimpl_get_values()._p_.del_informations()
|
||||
# Option's properties
|
||||
self._config_bag.context.cfgimpl_get_settings()._p_.importation({})
|
||||
await self._config_bag.context.cfgimpl_get_settings()._p_.importation({})
|
||||
# Option's permissives
|
||||
self._config_bag.context.cfgimpl_get_settings()._pp_.importation({})
|
||||
await self._config_bag.context.cfgimpl_get_settings()._pp_.importation({})
|
||||
# Remove cache
|
||||
self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
await self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
|
||||
|
||||
class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset):
|
||||
"""Actions to Config"""
|
||||
def name(self):
|
||||
async def name(self):
|
||||
return self._config_bag.context.impl_getname()
|
||||
|
||||
def copy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None):
|
||||
async def copy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None):
|
||||
"""Copy current config"""
|
||||
return self._return_config(self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage))
|
||||
return await self._return_config(await self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage))
|
||||
|
||||
def deepcopy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
metaconfig_prefix=None):
|
||||
async def deepcopy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
metaconfig_prefix=None):
|
||||
"""Copy current config with all parents"""
|
||||
return self._return_config(self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
deep=[]))
|
||||
return await self._return_config(await self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
deep=[]))
|
||||
|
||||
def metaconfig(self):
|
||||
async def metaconfig(self):
|
||||
"""Get first meta configuration (obsolete please use parents)"""
|
||||
try:
|
||||
return next(self.parents())
|
||||
except StopIteration:
|
||||
parent = await self.parents()
|
||||
if not parent:
|
||||
return None
|
||||
return parent[0]
|
||||
|
||||
def parents(self):
|
||||
async def parents(self):
|
||||
"""Get all parents of current config"""
|
||||
ret = []
|
||||
for parent in self._config_bag.context.get_parents():
|
||||
yield self._return_config(parent)
|
||||
ret.append(await self._return_config(parent))
|
||||
return ret
|
||||
|
||||
def path(self):
|
||||
async def path(self):
|
||||
"""Get path from config (all parents name)"""
|
||||
return self._config_bag.context.cfgimpl_get_config_path()
|
||||
|
||||
|
||||
class _TiramisuContextGroupConfig(TiramisuConfig):
|
||||
"""Actions to GroupConfig"""
|
||||
def name(self):
|
||||
async def name(self):
|
||||
"""Get config name"""
|
||||
return self._config_bag.context.impl_getname()
|
||||
|
||||
def list(self):
|
||||
async def list(self):
|
||||
"""List children's config"""
|
||||
ret = []
|
||||
for child in self._config_bag.context.cfgimpl_get_children():
|
||||
yield self._return_config(child)
|
||||
ret.append(await self._return_config(child))
|
||||
return ret
|
||||
|
||||
def find(self,
|
||||
name: str,
|
||||
value=undefined):
|
||||
async def find(self,
|
||||
name: str,
|
||||
value=undefined):
|
||||
"""Find an or a list of config with finding option"""
|
||||
return GroupConfig(self._config_bag.context.find_group(byname=name,
|
||||
byvalue=value,
|
||||
config_bag=self._config_bag))
|
||||
return await GroupConfig(await self._config_bag.context.find_group(byname=name,
|
||||
byvalue=value,
|
||||
config_bag=self._config_bag))
|
||||
|
||||
def __call__(self,
|
||||
path: Optional[str]):
|
||||
"""select a child Tiramisu config"""
|
||||
if path is None:
|
||||
return self._return_config(self._config_bag.context)
|
||||
spaths = path.split('.')
|
||||
config = self._config_bag.context
|
||||
for spath in spaths:
|
||||
config = config.getconfig(spath)
|
||||
return self._return_config(config)
|
||||
|
||||
def copy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None):
|
||||
return self._return_config(self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage))
|
||||
async def copy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None):
|
||||
return await self._return_config(await self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage))
|
||||
|
||||
def deepcopy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
metaconfig_prefix=None):
|
||||
return self._return_config(self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
deep=[]))
|
||||
async def deepcopy(self,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
metaconfig_prefix=None):
|
||||
return await self._return_config(await self._config_bag.context.duplicate(session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
deep=[]))
|
||||
|
||||
def path(self):
|
||||
async def path(self):
|
||||
return self._config_bag.context.cfgimpl_get_config_path()
|
||||
|
||||
def get(self,
|
||||
name: str) -> 'Config':
|
||||
return self._return_config(self._config_bag.context.getconfig(name))
|
||||
async def get(self,
|
||||
name: str) -> 'Config':
|
||||
return await self._return_config(self._config_bag.context.getconfig(name))
|
||||
|
||||
|
||||
class _TiramisuContextMixConfig(_TiramisuContextGroupConfig, _TiramisuContextConfigReset):
|
||||
"""Actions to MixConfig"""
|
||||
def pop(self,
|
||||
session_id=None,
|
||||
config=None):
|
||||
async def pop(self,
|
||||
session_id=None,
|
||||
config=None):
|
||||
"""Remove config from MetaConfig"""
|
||||
if __debug__ and None not in [session_id, config]:
|
||||
raise APIError(_('cannot set session_id and config together'))
|
||||
return self._return_config(self._config_bag.context.pop_config(session_id=session_id, config=config))
|
||||
pop_config = await self._config_bag.context.pop_config(session_id=session_id, config=config)
|
||||
return await self._return_config(pop_config)
|
||||
|
||||
def add(self,
|
||||
config):
|
||||
async def add(self,
|
||||
config):
|
||||
"""Add config from MetaConfig"""
|
||||
self._config_bag.context.add_config(config)
|
||||
await self._config_bag.context.add_config(config)
|
||||
|
||||
def parents(self):
|
||||
async def parents(self):
|
||||
"""Get all parents of current config"""
|
||||
ret = []
|
||||
for parent in self._config_bag.context.get_parents():
|
||||
yield self._return_config(parent)
|
||||
ret.append(await self._return_config(parent))
|
||||
return ret
|
||||
|
||||
|
||||
class _TiramisuContextMetaConfig(_TiramisuContextMixConfig):
|
||||
"""Actions to MetaConfig"""
|
||||
def new(self,
|
||||
session_id,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
type='config'):
|
||||
async def new(self,
|
||||
session_id,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
type='config'):
|
||||
"""Create and add a new config"""
|
||||
new_config = self._config_bag.context.new_config(session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
type_=type)
|
||||
return self._return_config(new_config)
|
||||
new_config = await self._config_bag.context.new_config(session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
type_=type)
|
||||
return await self._return_config(new_config)
|
||||
|
||||
|
||||
|
||||
class TiramisuContextCache(TiramisuConfig):
|
||||
def reset(self):
|
||||
self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
async def reset(self):
|
||||
await self._config_bag.context.cfgimpl_reset_cache(None, None)
|
||||
|
||||
def set_expiration_time(self,
|
||||
async def set_expiration_time(self,
|
||||
time: int) -> None:
|
||||
self._config_bag.expiration_time = time
|
||||
|
||||
def get_expiration_time(self) -> int:
|
||||
async def get_expiration_time(self) -> int:
|
||||
return self._config_bag.expiration_time
|
||||
|
||||
|
||||
class TiramisuDispatcher:
|
||||
pass
|
||||
|
||||
|
||||
class TiramisuAPI(TiramisuHelp):
|
||||
_registers = {}
|
||||
|
||||
def __init__(self,
|
||||
config) -> None:
|
||||
if not isinstance(config, ConfigBag):
|
||||
config = ConfigBag(context=config)
|
||||
self._config_bag = config
|
||||
config_bag,
|
||||
orig_config_bags=None) -> None:
|
||||
if not isinstance(config_bag, ConfigBag):
|
||||
raise Exception('pfffff')
|
||||
# config = await ConfigBag(context=config)
|
||||
self._config_bag = config_bag
|
||||
self._orig_config_bags = orig_config_bags
|
||||
if not self._registers:
|
||||
_registers(self._registers, 'TiramisuContext')
|
||||
_registers(self._registers, 'TiramisuDispatcher')
|
||||
|
||||
def __getattr__(self, subfunc: str) -> Any:
|
||||
if subfunc == 'forcepermissive':
|
||||
if subfunc == 'option':
|
||||
config_bag = self._config_bag
|
||||
return TiramisuDispatcherOption(config_bag,
|
||||
self._orig_config_bags)
|
||||
elif subfunc == 'forcepermissive':
|
||||
config_bag = self._config_bag.copy()
|
||||
config_bag.set_permissive()
|
||||
return TiramisuAPI(config_bag)
|
||||
if self._orig_config_bags is None:
|
||||
orig_config_bags = []
|
||||
else:
|
||||
orig_config_bags = self._orig_config_bags
|
||||
orig_config_bags.append(self._config_bag)
|
||||
return TiramisuAPI(config_bag, orig_config_bags)
|
||||
elif subfunc == 'unrestraint':
|
||||
config_bag = self._config_bag.copy()
|
||||
config_bag.unrestraint()
|
||||
return TiramisuAPI(config_bag)
|
||||
if self._orig_config_bags is None:
|
||||
orig_config_bags = []
|
||||
else:
|
||||
orig_config_bags = self._orig_config_bags
|
||||
orig_config_bags.append(self._config_bag)
|
||||
return TiramisuAPI(config_bag, orig_config_bags)
|
||||
elif subfunc == 'config':
|
||||
config_type = self._config_bag.context.impl_type
|
||||
if config_type == 'group':
|
||||
@ -1509,70 +1461,73 @@ class TiramisuAPI(TiramisuHelp):
|
||||
config = _TiramisuContextMixConfig
|
||||
else:
|
||||
config = _TiramisuContextConfig
|
||||
return config(self._config_bag)
|
||||
return config(self._config_bag,
|
||||
self._orig_config_bags)
|
||||
elif subfunc in self._registers:
|
||||
config_bag = self._config_bag
|
||||
del config_bag.permissives
|
||||
return self._registers[subfunc](config_bag)
|
||||
# del config_bag.permissives
|
||||
return self._registers[subfunc](config_bag,
|
||||
self._orig_config_bags)
|
||||
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
|
||||
|
||||
def __dir__(self):
|
||||
return list(self._registers.keys()) + ['unrestraint', 'forcepermissive', 'config']
|
||||
|
||||
|
||||
class TiramisuDispatcherOption(TiramisuDispatcher, TiramisuContextOption):
|
||||
class TiramisuDispatcherOption(TiramisuContextOption):
|
||||
"""Select an option"""
|
||||
def __call__(self,
|
||||
path: str,
|
||||
index: Optional[int]=None) -> TiramisuOption:
|
||||
"""Select an option by path"""
|
||||
if self._config_bag.context.impl_type == 'group':
|
||||
subpath, name = path.rsplit('.', 1)
|
||||
subconfig = None
|
||||
else:
|
||||
subconfig, name = self._config_bag.context.cfgimpl_get_home_by_path(path,
|
||||
self._config_bag)
|
||||
return TiramisuOption(name,
|
||||
path,
|
||||
return TiramisuOption(path,
|
||||
index,
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
|
||||
def __getattr__(self, subfunc: str) -> Any:
|
||||
async def __getattr__(self,
|
||||
subfunc: str) -> Any:
|
||||
if subfunc == 'unrestraint':
|
||||
config_bag = self._config_bag.copy()
|
||||
config_bag.unrestraint()
|
||||
return TiramisuDispatcherOption(config_bag)
|
||||
|
||||
|
||||
@asyncinit
|
||||
class Config(TiramisuAPI):
|
||||
"""Root config object that enables us to handle the configuration options"""
|
||||
def __init__(self,
|
||||
descr: OptionDescription,
|
||||
session_id: str=None,
|
||||
persistent: bool=False,
|
||||
storage=None,
|
||||
display_name=None) -> None:
|
||||
async def __init__(self,
|
||||
descr: OptionDescription,
|
||||
session_id: str=None,
|
||||
persistent: bool=False,
|
||||
storage=None,
|
||||
display_name=None) -> None:
|
||||
if isinstance(descr, KernelConfig):
|
||||
config = descr
|
||||
else:
|
||||
config = KernelConfig(descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=display_name)
|
||||
super().__init__(config)
|
||||
config = await KernelConfig(descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=display_name)
|
||||
settings = config.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(config._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
config_bag = ConfigBag(config,
|
||||
properties=properties,
|
||||
permissives=permissives)
|
||||
super().__init__(config_bag)
|
||||
|
||||
|
||||
@asyncinit
|
||||
class MetaConfig(TiramisuAPI):
|
||||
"""MetaConfig object that enables us to handle the sub configuration's options"""
|
||||
def __init__(self,
|
||||
children: 'Config'=[],
|
||||
session_id: Union[str, None]=None,
|
||||
persistent: bool=False,
|
||||
optiondescription: Optional[OptionDescription]=None,
|
||||
storage=None,
|
||||
display_name=None) -> None:
|
||||
async def __init__(self,
|
||||
children: 'Config'=[],
|
||||
session_id: Union[str, None]=None,
|
||||
persistent: bool=False,
|
||||
optiondescription: Optional[OptionDescription]=None,
|
||||
storage=None,
|
||||
display_name=None) -> None:
|
||||
if isinstance(children, KernelMetaConfig):
|
||||
config = children
|
||||
else:
|
||||
@ -1583,24 +1538,31 @@ class MetaConfig(TiramisuAPI):
|
||||
else:
|
||||
_children.append(child)
|
||||
|
||||
config = KernelMetaConfig(_children,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
optiondescription=optiondescription,
|
||||
display_name=display_name,
|
||||
storage=storage)
|
||||
super().__init__(config)
|
||||
config = await KernelMetaConfig(_children,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
optiondescription=optiondescription,
|
||||
display_name=display_name,
|
||||
storage=storage)
|
||||
settings = config.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(config._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
config_bag = ConfigBag(config,
|
||||
properties=properties,
|
||||
permissives=permissives)
|
||||
super().__init__(config_bag)
|
||||
|
||||
|
||||
@asyncinit
|
||||
class MixConfig(TiramisuAPI):
|
||||
"""MetaConfig object that enables us to handle the sub configuration's options"""
|
||||
def __init__(self,
|
||||
optiondescription: OptionDescription,
|
||||
children: List[Config],
|
||||
session_id: Optional[str]=None,
|
||||
persistent: bool=False,
|
||||
storage=None,
|
||||
display_name: Callable=None) -> None:
|
||||
async def __init__(self,
|
||||
optiondescription: OptionDescription,
|
||||
children: List[Config],
|
||||
session_id: Optional[str]=None,
|
||||
persistent: bool=False,
|
||||
storage=None,
|
||||
display_name: Callable=None) -> None:
|
||||
if isinstance(children, KernelMixConfig):
|
||||
config = children
|
||||
else:
|
||||
@ -1611,20 +1573,27 @@ class MixConfig(TiramisuAPI):
|
||||
else:
|
||||
_children.append(child)
|
||||
|
||||
config = KernelMixConfig(optiondescription,
|
||||
_children,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=display_name)
|
||||
super().__init__(config)
|
||||
config = await KernelMixConfig(optiondescription,
|
||||
_children,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=display_name)
|
||||
settings = config.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(config._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
config_bag = ConfigBag(config,
|
||||
properties=properties,
|
||||
permissives=permissives)
|
||||
super().__init__(config_bag)
|
||||
|
||||
|
||||
@asyncinit
|
||||
class GroupConfig(TiramisuAPI):
|
||||
"""GroupConfig that enables us to access the Config"""
|
||||
def __init__(self,
|
||||
children,
|
||||
session_id: Optional[str]=None) -> None:
|
||||
async def __init__(self,
|
||||
children,
|
||||
session_id: Optional[str]=None) -> None:
|
||||
if isinstance(children, KernelGroupConfig):
|
||||
config = children
|
||||
else:
|
||||
@ -1635,6 +1604,9 @@ class GroupConfig(TiramisuAPI):
|
||||
else:
|
||||
_children.append(child)
|
||||
|
||||
config = KernelGroupConfig(_children,
|
||||
session_id=session_id)
|
||||
super().__init__(config)
|
||||
config = await KernelGroupConfig(_children,
|
||||
session_id=session_id)
|
||||
config_bag = ConfigBag(config,
|
||||
properties=None,
|
||||
permissives=None)
|
||||
super().__init__(config_bag)
|
||||
|
@ -24,7 +24,6 @@ from itertools import chain
|
||||
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
|
||||
from .i18n import _
|
||||
from .setting import undefined, ConfigBag, OptionBag, Undefined
|
||||
from .storage import get_default_values_storages, get_default_settings_storages
|
||||
# ____________________________________________________________
|
||||
|
||||
|
||||
@ -99,10 +98,6 @@ class ParamValue(Param):
|
||||
self.value = value
|
||||
|
||||
|
||||
class ParamContext(Param):
|
||||
__slots__ = tuple()
|
||||
|
||||
|
||||
class ParamIndex(Param):
|
||||
__slots__ = tuple()
|
||||
|
||||
@ -137,32 +132,32 @@ class Calculation:
|
||||
if warnings_only is True:
|
||||
self.warnings_only = warnings_only
|
||||
|
||||
def execute(self,
|
||||
async def execute(self,
|
||||
option_bag: OptionBag,
|
||||
leadership_must_have_index: bool=False,
|
||||
orig_value: Any=undefined,
|
||||
allow_raises=False) -> Any:
|
||||
return carry_out_calculation(option_bag.option,
|
||||
callback=self.function,
|
||||
callback_params=self.params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag,
|
||||
leadership_must_have_index=leadership_must_have_index,
|
||||
orig_value=orig_value,
|
||||
allow_raises=allow_raises)
|
||||
return await carry_out_calculation(option_bag.option,
|
||||
callback=self.function,
|
||||
callback_params=self.params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag,
|
||||
leadership_must_have_index=leadership_must_have_index,
|
||||
orig_value=orig_value,
|
||||
allow_raises=allow_raises)
|
||||
|
||||
def help(self,
|
||||
option_bag: OptionBag,
|
||||
leadership_must_have_index: bool=False) -> str:
|
||||
async def help(self,
|
||||
option_bag: OptionBag,
|
||||
leadership_must_have_index: bool=False) -> str:
|
||||
if not self.help_function:
|
||||
return self.execute(option_bag,
|
||||
leadership_must_have_index=leadership_must_have_index)
|
||||
return carry_out_calculation(option_bag.option,
|
||||
callback=self.help_function,
|
||||
callback_params=self.params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag,
|
||||
leadership_must_have_index=leadership_must_have_index)
|
||||
return await carry_out_calculation(option_bag.option,
|
||||
callback=self.help_function,
|
||||
callback_params=self.params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag,
|
||||
leadership_must_have_index=leadership_must_have_index)
|
||||
|
||||
def has_index(self, current_option):
|
||||
if hasattr(self, '_has_index'):
|
||||
@ -180,12 +175,12 @@ class Break(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
option,
|
||||
index: Optional[int],
|
||||
orig_value,
|
||||
config_bag: ConfigBag,
|
||||
leadership_must_have_index: bool) -> Any:
|
||||
async def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
option,
|
||||
index: Optional[int],
|
||||
orig_value,
|
||||
config_bag: ConfigBag,
|
||||
leadership_must_have_index: bool) -> Any:
|
||||
"""replace Param by true value"""
|
||||
def calc_index(callbk, index, same_leadership):
|
||||
if index is not None:
|
||||
@ -199,7 +194,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
return index
|
||||
return None
|
||||
|
||||
def calc_self(callbk, option, index, value, config_bag):
|
||||
async def calc_self(callbk, option, index, value, config_bag):
|
||||
# index must be apply only if follower
|
||||
is_follower = option.impl_is_follower()
|
||||
apply_index = calc_index(callbk, index, is_follower)
|
||||
@ -207,13 +202,13 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
if config_bag is undefined:
|
||||
return undefined
|
||||
path = option.impl_getpath()
|
||||
option_bag = get_option_bag(config_bag, option, path, apply_index)
|
||||
option_bag = await get_option_bag(config_bag, option, path, apply_index)
|
||||
option_bag.config_bag.unrestraint()
|
||||
option_bag.config_bag.remove_validation()
|
||||
# if we are in properties calculation, cannot calculated properties
|
||||
option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
|
||||
apply_requires=False)
|
||||
new_value = get_value(callbk, option_bag, path)
|
||||
option_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
|
||||
apply_requires=False)
|
||||
new_value = await get_value(callbk, option_bag, path)
|
||||
if apply_index is None and is_follower:
|
||||
new_value[index] = value
|
||||
value = new_value
|
||||
@ -221,11 +216,11 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
value = value[apply_index]
|
||||
return value
|
||||
|
||||
def get_value(callbk, option_bag, path):
|
||||
async def get_value(callbk, option_bag, path):
|
||||
try:
|
||||
# get value
|
||||
value = config_bag.context.getattr(path,
|
||||
option_bag)
|
||||
value = await config_bag.context.getattr(path,
|
||||
option_bag)
|
||||
except PropertiesOptionError as err:
|
||||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||
if callbk.notraisepropertyerror or callbk.raisepropertyerror:
|
||||
@ -236,7 +231,10 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option_bag.option.impl_get_display_name(), err))
|
||||
return value
|
||||
|
||||
def get_option_bag(config_bag, opt, path, index_):
|
||||
async def get_option_bag(config_bag,
|
||||
opt,
|
||||
path,
|
||||
index_):
|
||||
# don't validate if option is option that we tried to validate
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.properties = config_bag.true_properties - {'warnings'}
|
||||
@ -247,6 +245,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
path,
|
||||
index_,
|
||||
config_bag)
|
||||
option_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(option_bag)
|
||||
return option_bag
|
||||
|
||||
if isinstance(callbk, ParamValue):
|
||||
@ -260,16 +259,10 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
raise ConfigError('option "{}" is not in a dynoptiondescription'.format(option.impl_get_display_name()))
|
||||
return option.impl_getsuffix()
|
||||
|
||||
if isinstance(callbk, ParamContext):
|
||||
if config_bag is undefined:
|
||||
return undefined
|
||||
# Not an option, set full context
|
||||
return config_bag.context.duplicate(force_values=get_default_values_storages(),
|
||||
force_settings=get_default_settings_storages())
|
||||
if isinstance(callbk, ParamSelfOption):
|
||||
if leadership_must_have_index and option.impl_get_leadership() and index is None:
|
||||
raise Break()
|
||||
value = calc_self(callbk, option, index, orig_value, config_bag)
|
||||
value = await calc_self(callbk, option, index, orig_value, config_bag)
|
||||
if not callbk.todict:
|
||||
return value
|
||||
return {'name': option.impl_get_display_name(),
|
||||
@ -299,8 +292,8 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
index_ = None
|
||||
with_index = False
|
||||
path = callbk_option.impl_getpath()
|
||||
option_bag = get_option_bag(config_bag, callbk_option, path, index_)
|
||||
value = get_value(callbk, option_bag, path)
|
||||
option_bag = await get_option_bag(config_bag, callbk_option, path, index_)
|
||||
value = await get_value(callbk, option_bag, path)
|
||||
if with_index:
|
||||
value = value[index]
|
||||
if not callbk.todict:
|
||||
@ -309,14 +302,14 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
'value': value}
|
||||
|
||||
|
||||
def carry_out_calculation(option,
|
||||
callback: Callable,
|
||||
callback_params: Optional[Params],
|
||||
index: Optional[int],
|
||||
config_bag: Optional[ConfigBag],
|
||||
orig_value=undefined,
|
||||
leadership_must_have_index: bool=False,
|
||||
allow_raises: int=False):
|
||||
async def carry_out_calculation(option,
|
||||
callback: Callable,
|
||||
callback_params: Optional[Params],
|
||||
index: Optional[int],
|
||||
config_bag: Optional[ConfigBag],
|
||||
orig_value=undefined,
|
||||
leadership_must_have_index: bool=False,
|
||||
allow_raises: int=False):
|
||||
"""a function that carries out a calculation for an option's value
|
||||
|
||||
:param option: the option
|
||||
@ -342,12 +335,12 @@ def carry_out_calculation(option,
|
||||
if callback_params:
|
||||
for key, callbk in chain(fake_items(callback_params.args), callback_params.kwargs.items()):
|
||||
try:
|
||||
value = manager_callback(callbk,
|
||||
option,
|
||||
index,
|
||||
orig_value,
|
||||
config_bag,
|
||||
leadership_must_have_index)
|
||||
value = await manager_callback(callbk,
|
||||
option,
|
||||
index,
|
||||
orig_value,
|
||||
config_bag,
|
||||
leadership_must_have_index)
|
||||
if value is undefined:
|
||||
return undefined
|
||||
if key is None:
|
||||
|
1042
tiramisu/config.py
1042
tiramisu/config.py
@ -31,9 +31,11 @@ from .setting import OptionBag, ConfigBag, Settings, undefined, groups
|
||||
from .storage import get_storages, gen_storage_id, get_default_values_storages, list_sessions, Cache
|
||||
from .value import Values
|
||||
from .i18n import _
|
||||
from .asyncinit import asyncinit
|
||||
|
||||
|
||||
class SubConfig(object):
|
||||
@asyncinit
|
||||
class SubConfig:
|
||||
"""Sub configuration management entry.
|
||||
Tree if OptionDescription's responsability. SubConfig are generated
|
||||
on-demand. A Config is also a SubConfig.
|
||||
@ -44,11 +46,11 @@ class SubConfig(object):
|
||||
'_impl_path',
|
||||
'_impl_length')
|
||||
|
||||
def __init__(self,
|
||||
descr,
|
||||
context,
|
||||
config_bag,
|
||||
subpath=None):
|
||||
async def __init__(self,
|
||||
descr,
|
||||
context,
|
||||
config_bag=None,
|
||||
subpath=None):
|
||||
""" Configuration option management class
|
||||
|
||||
:param descr: describes the configuration schema
|
||||
@ -81,28 +83,29 @@ class SubConfig(object):
|
||||
full_leaderpath,
|
||||
None,
|
||||
cconfig_bag)
|
||||
value = self.getattr(leaderpath,
|
||||
moption_bag)
|
||||
moption_bag.properties = await self.cfgimpl_get_settings().getproperties(moption_bag)
|
||||
value = await self.getattr(leaderpath,
|
||||
moption_bag)
|
||||
self._impl_length = len(value)
|
||||
|
||||
def cfgimpl_get_length(self):
|
||||
return self._impl_length
|
||||
|
||||
def cfgimpl_get_length_leadership(self,
|
||||
async def cfgimpl_get_length_leadership(self,
|
||||
option_bag):
|
||||
if option_bag.option.impl_is_symlinkoption():
|
||||
context = self.cfgimpl_get_context()
|
||||
path = option_bag.option.impl_getopt().impl_getpath()
|
||||
subconfig, _ = context.cfgimpl_get_home_by_path(path,
|
||||
option_bag.config_bag)
|
||||
subconfig, _ = await context.cfgimpl_get_home_by_path(path,
|
||||
option_bag.config_bag)
|
||||
return subconfig.cfgimpl_get_length()
|
||||
else:
|
||||
return self.cfgimpl_get_length()
|
||||
|
||||
def reset_one_option_cache(self,
|
||||
desc,
|
||||
resetted_opts,
|
||||
option_bag):
|
||||
async def reset_one_option_cache(self,
|
||||
desc,
|
||||
resetted_opts,
|
||||
option_bag):
|
||||
|
||||
if option_bag.path in resetted_opts:
|
||||
return
|
||||
@ -110,9 +113,9 @@ class SubConfig(object):
|
||||
for woption in option_bag.option._get_dependencies(self.cfgimpl_get_description()):
|
||||
option = woption()
|
||||
if option.impl_is_dynoptiondescription():
|
||||
# it's a dynoptiondescription remove cache for all generated optiondescription
|
||||
for suffix in option.get_suffixes(option_bag.config_bag):
|
||||
doption = option.to_dynoption(desc.impl_getpath(),
|
||||
subpath = option.impl_getpath().rsplit('.', 1)[0]
|
||||
for suffix in await option.get_suffixes(option_bag.config_bag):
|
||||
doption = option.to_dynoption(subpath,
|
||||
suffix,
|
||||
option)
|
||||
doption_path = doption.impl_getpath()
|
||||
@ -121,15 +124,16 @@ class SubConfig(object):
|
||||
doption_path,
|
||||
option_bag.index,
|
||||
option_bag.config_bag)
|
||||
self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag)
|
||||
await self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
elif option.issubdyn():
|
||||
# it's an option in dynoptiondescription, remove cache for all generated option
|
||||
dynopt = option.getsubdyn()
|
||||
rootpath = dynopt.impl_getpath()
|
||||
subpaths = [rootpath] + option.impl_getpath()[len(rootpath) + 1:].split('.')[:-1]
|
||||
for suffix in dynopt.get_suffixes(option_bag.config_bag):
|
||||
for suffix in await dynopt.get_suffixes(option_bag.config_bag):
|
||||
path_suffix = dynopt.convert_suffix_to_path(suffix)
|
||||
subpath = '.'.join([subp + path_suffix for subp in subpaths])
|
||||
doption = option.to_dynoption(subpath,
|
||||
@ -141,9 +145,10 @@ class SubConfig(object):
|
||||
doption_path,
|
||||
option_bag.index,
|
||||
option_bag.config_bag)
|
||||
self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag)
|
||||
await self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
else:
|
||||
option_path = option.impl_getpath()
|
||||
doption_bag = OptionBag()
|
||||
@ -151,17 +156,18 @@ class SubConfig(object):
|
||||
option_path,
|
||||
option_bag.index,
|
||||
option_bag.config_bag)
|
||||
self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag)
|
||||
await self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
doption_bag)
|
||||
del option
|
||||
option_bag.option.reset_cache(option_bag.path,
|
||||
option_bag.config_bag,
|
||||
resetted_opts)
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
option_bag,
|
||||
resetted_opts=None):
|
||||
async def cfgimpl_reset_cache(self,
|
||||
option_bag,
|
||||
resetted_opts=None):
|
||||
"""reset all settings in cache
|
||||
"""
|
||||
if resetted_opts is None:
|
||||
@ -169,31 +175,33 @@ class SubConfig(object):
|
||||
|
||||
context = self.cfgimpl_get_context()
|
||||
desc = context.cfgimpl_get_description()
|
||||
|
||||
if option_bag is not None:
|
||||
self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
option_bag)
|
||||
await self.reset_one_option_cache(desc,
|
||||
resetted_opts,
|
||||
option_bag)
|
||||
else:
|
||||
context._impl_values_cache.reset_all_cache()
|
||||
context._impl_properties_cache.reset_all_cache()
|
||||
|
||||
def cfgimpl_get_home_by_path(self,
|
||||
path,
|
||||
config_bag):
|
||||
async def cfgimpl_get_home_by_path(self,
|
||||
path: str,
|
||||
config_bag: ConfigBag,
|
||||
validate_properties=True) -> ('Subconfig', str):
|
||||
""":returns: tuple (config, name)"""
|
||||
path = path.split('.')
|
||||
for step in path[:-1]:
|
||||
option_bag = OptionBag()
|
||||
option = self.cfgimpl_get_description().get_child(step,
|
||||
config_bag,
|
||||
self.cfgimpl_get_path())
|
||||
option = await self.cfgimpl_get_description().get_child(step,
|
||||
config_bag,
|
||||
self.cfgimpl_get_path())
|
||||
subpath = self._get_subpath(step)
|
||||
option_bag.set_option(option,
|
||||
subpath,
|
||||
None,
|
||||
config_bag)
|
||||
self = self.get_subconfig(option_bag)
|
||||
option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag)
|
||||
self = await self.get_subconfig(option_bag,
|
||||
validate_properties)
|
||||
assert isinstance(self, SubConfig), _('unknown option {}').format(path[-1])
|
||||
return self, path[-1]
|
||||
|
||||
@ -212,35 +220,35 @@ class SubConfig(object):
|
||||
def cfgimpl_get_values(self):
|
||||
return self.cfgimpl_get_context()._impl_values
|
||||
|
||||
def setattr(self,
|
||||
value,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
async def setattr(self,
|
||||
value,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
|
||||
if option_bag.option.impl_is_symlinkoption():
|
||||
raise ConfigError(_("can't set value to a SymLinkOption"))
|
||||
context = option_bag.config_bag.context
|
||||
context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
await context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
if option_bag.option.impl_is_leader() and len(value) < self._impl_length:
|
||||
raise LeadershipError(_('cannot reduce length of the leader "{}"'
|
||||
'').format(option_bag.option.impl_get_display_name()))
|
||||
return context.cfgimpl_get_values().setvalue(value,
|
||||
option_bag,
|
||||
_commit)
|
||||
return await context.cfgimpl_get_values().setvalue(value,
|
||||
option_bag,
|
||||
_commit)
|
||||
|
||||
def delattr(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
async def delattr(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
option = option_bag.option
|
||||
if option.impl_is_symlinkoption():
|
||||
raise ConfigError(_("can't delete a SymLinkOption"))
|
||||
values = self.cfgimpl_get_values()
|
||||
if option_bag.index is not None:
|
||||
values.reset_follower(option_bag,
|
||||
_commit)
|
||||
await values.reset_follower(option_bag,
|
||||
_commit)
|
||||
else:
|
||||
values.reset(option_bag,
|
||||
_commit)
|
||||
await values.reset(option_bag,
|
||||
_commit)
|
||||
|
||||
def _get_subpath(self, name):
|
||||
if self._impl_path is None:
|
||||
@ -249,27 +257,29 @@ class SubConfig(object):
|
||||
subpath = self._impl_path + '.' + name
|
||||
return subpath
|
||||
|
||||
def get_subconfig(self,
|
||||
option_bag):
|
||||
self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
return SubConfig(option_bag.option,
|
||||
self._impl_context,
|
||||
option_bag.config_bag,
|
||||
option_bag.path)
|
||||
async def get_subconfig(self,
|
||||
option_bag: OptionBag,
|
||||
validate_properties: bool=True) -> 'SubConfig':
|
||||
if validate_properties:
|
||||
await self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
return await SubConfig(option_bag.option,
|
||||
self._impl_context,
|
||||
option_bag.config_bag,
|
||||
option_bag.path)
|
||||
|
||||
def getattr(self,
|
||||
name,
|
||||
option_bag,
|
||||
from_follower=False,
|
||||
needs_re_verify_follower_properties=False):
|
||||
async def getattr(self,
|
||||
name,
|
||||
option_bag,
|
||||
from_follower=False,
|
||||
needs_re_verify_follower_properties=False):
|
||||
"""
|
||||
:return: option's value if name is an option name, OptionDescription
|
||||
otherwise
|
||||
"""
|
||||
config_bag = option_bag.config_bag
|
||||
if '.' in name:
|
||||
self, name = self.cfgimpl_get_home_by_path(name,
|
||||
config_bag)
|
||||
self, name = await self.cfgimpl_get_home_by_path(name,
|
||||
config_bag)
|
||||
|
||||
option = option_bag.option
|
||||
if option.impl_is_symlinkoption():
|
||||
@ -278,22 +288,23 @@ class SubConfig(object):
|
||||
None,
|
||||
option_bag.index,
|
||||
config_bag)
|
||||
soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag)
|
||||
soption_bag.ori_option = option
|
||||
context = self.cfgimpl_get_context()
|
||||
return context.getattr(soption_bag.path,
|
||||
return await context.getattr(soption_bag.path,
|
||||
soption_bag)
|
||||
|
||||
#if not from_follower or needs_re_verify_follower_properties:
|
||||
if option.impl_is_follower() and not from_follower:
|
||||
needs_re_verify_follower_properties = self.cfgimpl_get_settings().has_properties_index(option_bag)
|
||||
needs_re_verify_follower_properties = await self.cfgimpl_get_settings().has_properties_index(option_bag)
|
||||
if not option.impl_is_follower() or \
|
||||
(needs_re_verify_follower_properties and option_bag.index is not None) or \
|
||||
(needs_re_verify_follower_properties and option_bag.index is not None) or \
|
||||
(not needs_re_verify_follower_properties and (not from_follower or option_bag.index is None)):
|
||||
self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
await self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
|
||||
if option.impl_is_follower() and not from_follower:
|
||||
length = self.cfgimpl_get_length_leadership(option_bag)
|
||||
follower_len = self.cfgimpl_get_values()._p_.get_max_length(option_bag.path)
|
||||
length = await self.cfgimpl_get_length_leadership(option_bag)
|
||||
follower_len = await self.cfgimpl_get_values()._p_.get_max_length(option_bag.path)
|
||||
if follower_len > length:
|
||||
raise LeadershipError(_('the follower option "{}" has greater length ({}) than the leader '
|
||||
'length ({})').format(option.impl_get_display_name(),
|
||||
@ -308,39 +319,40 @@ class SubConfig(object):
|
||||
option_bag.path,
|
||||
idx,
|
||||
config_bag)
|
||||
soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag)
|
||||
try:
|
||||
value.append(self.getattr(name,
|
||||
soption_bag,
|
||||
from_follower=True,
|
||||
needs_re_verify_follower_properties=needs_re_verify_follower_properties))
|
||||
value.append(await self.getattr(name,
|
||||
soption_bag,
|
||||
from_follower=True,
|
||||
needs_re_verify_follower_properties=needs_re_verify_follower_properties))
|
||||
except PropertiesOptionError as err:
|
||||
value.append(err)
|
||||
else:
|
||||
value = self.cfgimpl_get_values().get_cached_value(option_bag)
|
||||
value = await self.cfgimpl_get_values().get_cached_value(option_bag)
|
||||
self.cfgimpl_get_settings().validate_mandatory(value,
|
||||
option_bag)
|
||||
return value
|
||||
|
||||
def find(self,
|
||||
bytype,
|
||||
byname,
|
||||
byvalue,
|
||||
config_bag,
|
||||
_subpath=None,
|
||||
raise_if_not_found=True,
|
||||
only_path=undefined,
|
||||
only_option=undefined,
|
||||
with_option=False):
|
||||
async def find(self,
|
||||
bytype,
|
||||
byname,
|
||||
byvalue,
|
||||
config_bag,
|
||||
_subpath=None,
|
||||
raise_if_not_found=True,
|
||||
only_path=undefined,
|
||||
only_option=undefined,
|
||||
with_option=False):
|
||||
"""
|
||||
convenience method for finding an option that lives only in the subtree
|
||||
|
||||
:param first: return only one option if True, a list otherwise
|
||||
:return: find list or an exception if nothing has been found
|
||||
"""
|
||||
def _filter_by_value(soption_bag):
|
||||
async def _filter_by_value(soption_bag):
|
||||
try:
|
||||
value = context.getattr(path,
|
||||
soption_bag)
|
||||
value = await context.getattr(path,
|
||||
soption_bag)
|
||||
except PropertiesOptionError:
|
||||
return False
|
||||
if isinstance(value, list):
|
||||
@ -350,34 +362,37 @@ class SubConfig(object):
|
||||
|
||||
found = False
|
||||
if only_path is not undefined:
|
||||
options = [only_option]
|
||||
async def _fake_iter():
|
||||
yield only_option
|
||||
options = _fake_iter()
|
||||
else:
|
||||
options = self.cfgimpl_get_description().get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag)
|
||||
context = self.cfgimpl_get_context()
|
||||
for option in options:
|
||||
async for option in options:
|
||||
option_bag = OptionBag()
|
||||
path = option.impl_getpath()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
None,
|
||||
config_bag)
|
||||
if byvalue is not undefined and not _filter_by_value(option_bag):
|
||||
option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag)
|
||||
if byvalue is not undefined and not await _filter_by_value(option_bag):
|
||||
continue
|
||||
elif config_bag.properties:
|
||||
#remove option with propertyerror, ...
|
||||
try:
|
||||
if '.' in path:
|
||||
subconfig, subpath = context.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
subconfig, subpath = await context.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
else:
|
||||
subconfig = self
|
||||
subpath = path
|
||||
subconfig.cfgimpl_get_description().get_child(subpath,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
await subconfig.cfgimpl_get_description().get_child(subpath,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
await self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
except PropertiesOptionError:
|
||||
continue
|
||||
found = True
|
||||
@ -395,13 +410,13 @@ class SubConfig(object):
|
||||
raise AttributeError(_("no option found in config"
|
||||
" with these criteria"))
|
||||
|
||||
def make_dict(self,
|
||||
config_bag,
|
||||
flatten=False,
|
||||
_currpath=None,
|
||||
withoption=None,
|
||||
withvalue=undefined,
|
||||
fullpath=False):
|
||||
async def make_dict(self,
|
||||
config_bag,
|
||||
flatten=False,
|
||||
_currpath=None,
|
||||
withoption=None,
|
||||
withvalue=undefined,
|
||||
fullpath=False):
|
||||
"""exports the whole config into a `dict`
|
||||
:returns: dict of Option's name (or path) and values
|
||||
"""
|
||||
@ -412,49 +427,50 @@ class SubConfig(object):
|
||||
raise ValueError(_("make_dict can't filtering with value without "
|
||||
"option"))
|
||||
context = self.cfgimpl_get_context()
|
||||
self._make_dict(context,
|
||||
config_bag,
|
||||
flatten,
|
||||
_currpath,
|
||||
withoption,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues)
|
||||
await self._make_dict(context,
|
||||
config_bag,
|
||||
flatten,
|
||||
_currpath,
|
||||
withoption,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues)
|
||||
return pathsvalues
|
||||
|
||||
def _make_dict(self,
|
||||
context,
|
||||
config_bag,
|
||||
flatten,
|
||||
_currpath,
|
||||
withoption,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues):
|
||||
async def _make_dict(self,
|
||||
context,
|
||||
config_bag,
|
||||
flatten,
|
||||
_currpath,
|
||||
withoption,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues):
|
||||
if withoption is not None:
|
||||
# Find all option with criteria
|
||||
# retrieve OptionDescription and make_dict on it
|
||||
mypath = self.cfgimpl_get_path()
|
||||
for path in context.find(bytype=None,
|
||||
byname=withoption,
|
||||
byvalue=withvalue,
|
||||
_subpath=self.cfgimpl_get_path(False),
|
||||
config_bag=config_bag):
|
||||
async for path in context.find(bytype=None,
|
||||
byname=withoption,
|
||||
byvalue=withvalue,
|
||||
_subpath=self.cfgimpl_get_path(False),
|
||||
config_bag=config_bag):
|
||||
path = '.'.join(path.split('.')[:-1])
|
||||
if '.' in path:
|
||||
subconfig, subpath = context.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
subconfig, subpath = await context.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
else:
|
||||
subconfig = context
|
||||
subpath = path
|
||||
opt = subconfig.cfgimpl_get_description().get_child(subpath,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
opt = await subconfig.cfgimpl_get_description().get_child(subpath,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(opt,
|
||||
path,
|
||||
None,
|
||||
config_bag)
|
||||
soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag)
|
||||
if mypath is not None:
|
||||
if mypath == path:
|
||||
withoption = None
|
||||
@ -466,18 +482,19 @@ class SubConfig(object):
|
||||
'should start with "{1}"'
|
||||
'').format(path, mypath)
|
||||
path = path[len(tmypath):]
|
||||
self._make_sub_dict(path,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
soption_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue)
|
||||
await self._make_sub_dict(path,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
soption_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue)
|
||||
|
||||
#withoption can be set to None below !
|
||||
if withoption is None:
|
||||
for opt in self.cfgimpl_get_description().get_children(config_bag):
|
||||
children = await self.cfgimpl_get_description().get_children(config_bag)
|
||||
for opt in children:
|
||||
name = opt.impl_getname()
|
||||
path = self._get_subpath(name)
|
||||
soption_bag = OptionBag()
|
||||
@ -485,48 +502,49 @@ class SubConfig(object):
|
||||
path,
|
||||
None,
|
||||
config_bag)
|
||||
self._make_sub_dict(name,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
soption_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue)
|
||||
soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag)
|
||||
await self._make_sub_dict(name,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
soption_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue)
|
||||
return pathsvalues
|
||||
|
||||
def _make_sub_dict(self,
|
||||
name,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
option_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue):
|
||||
async def _make_sub_dict(self,
|
||||
name,
|
||||
pathsvalues,
|
||||
_currpath,
|
||||
flatten,
|
||||
option_bag,
|
||||
fullpath,
|
||||
context,
|
||||
withvalue):
|
||||
option = option_bag.option
|
||||
if option.impl_is_optiondescription():
|
||||
try:
|
||||
self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
subconfig = SubConfig(option_bag.option,
|
||||
self._impl_context,
|
||||
option_bag.config_bag,
|
||||
option_bag.path)
|
||||
subconfig._make_dict(context,
|
||||
option_bag.config_bag,
|
||||
flatten,
|
||||
_currpath + [name],
|
||||
None,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues)
|
||||
await self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
subconfig = await SubConfig(option_bag.option,
|
||||
self._impl_context,
|
||||
option_bag.config_bag,
|
||||
option_bag.path)
|
||||
await subconfig._make_dict(context,
|
||||
option_bag.config_bag,
|
||||
flatten,
|
||||
_currpath + [name],
|
||||
None,
|
||||
withvalue,
|
||||
fullpath,
|
||||
pathsvalues)
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype in (['mandatory'], ['empty']):
|
||||
raise err
|
||||
else:
|
||||
try:
|
||||
ret = self.getattr(name,
|
||||
option_bag)
|
||||
ret = await self.getattr(name,
|
||||
option_bag)
|
||||
except PropertiesOptionError as err:
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
@ -559,93 +577,105 @@ class _CommonConfig(SubConfig):
|
||||
'parents',
|
||||
'impl_type')
|
||||
|
||||
def _impl_build_all_caches(self):
|
||||
async def _impl_build_all_caches(self):
|
||||
descr = self.cfgimpl_get_description()
|
||||
if not descr.impl_already_build_caches():
|
||||
descr._group_type = groups.root
|
||||
descr._build_cache(display_name=self._display_name)
|
||||
config_bag = ConfigBag(context=self)
|
||||
descr.impl_build_force_store_values(config_bag)
|
||||
await descr._build_cache(display_name=self._display_name)
|
||||
if not hasattr(descr, '_cache_force_store_values'):
|
||||
raise ConfigError(_('option description seems to be part of an other '
|
||||
'config'))
|
||||
|
||||
def get_parents(self):
|
||||
for parent in self.parents:
|
||||
yield parent()
|
||||
|
||||
# information
|
||||
def impl_set_information(self, key, value):
|
||||
async def impl_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._impl_values.set_information(key, value)
|
||||
await self._impl_values.set_information(key,
|
||||
value)
|
||||
|
||||
def impl_get_information(self, key, default=undefined):
|
||||
async def impl_get_information(self,
|
||||
key,
|
||||
default=undefined):
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
"""
|
||||
return self._impl_values.get_information(key, default)
|
||||
return await self._impl_values.get_information(key,
|
||||
default)
|
||||
|
||||
def impl_del_information(self, key, raises=True):
|
||||
self._impl_values.del_information(key, raises)
|
||||
async def impl_del_information(self,
|
||||
key,
|
||||
raises=True):
|
||||
await self._impl_values.del_information(key,
|
||||
raises)
|
||||
|
||||
def impl_list_information(self):
|
||||
return self._impl_values.list_information()
|
||||
async def impl_list_information(self):
|
||||
return await self._impl_values.list_information()
|
||||
|
||||
def __getstate__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _gen_fake_values(self):
|
||||
fake_config = KernelConfig(self._impl_descr,
|
||||
persistent=False,
|
||||
force_values=get_default_values_storages(),
|
||||
force_settings=self.cfgimpl_get_settings(),
|
||||
display_name=self._display_name)
|
||||
fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
|
||||
async def _gen_fake_values(self):
|
||||
fake_config = await KernelConfig(self._impl_descr,
|
||||
persistent=False,
|
||||
force_values=await get_default_values_storages(),
|
||||
force_settings=self.cfgimpl_get_settings(),
|
||||
display_name=self._display_name)
|
||||
export = await self.cfgimpl_get_values()._p_.exportation()
|
||||
await fake_config.cfgimpl_get_values()._p_.importation(export)
|
||||
fake_config.parents = self.parents
|
||||
return fake_config
|
||||
|
||||
def duplicate(self,
|
||||
session_id=None,
|
||||
force_values=None,
|
||||
force_settings=None,
|
||||
storage=None,
|
||||
persistent=False,
|
||||
metaconfig_prefix=None,
|
||||
child=None,
|
||||
deep=None):
|
||||
async def duplicate(self,
|
||||
session_id=None,
|
||||
force_values=None,
|
||||
force_settings=None,
|
||||
storage=None,
|
||||
persistent=False,
|
||||
metaconfig_prefix=None,
|
||||
child=None,
|
||||
deep=None):
|
||||
assert isinstance(self, (KernelConfig, KernelMixConfig)), _('cannot duplicate {}').format(self.__class__.__name__)
|
||||
if isinstance(self, KernelConfig):
|
||||
duplicated_config = KernelConfig(self._impl_descr,
|
||||
_duplicate=True,
|
||||
session_id=session_id,
|
||||
force_values=force_values,
|
||||
force_settings=force_settings,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
duplicated_config = await KernelConfig(self._impl_descr,
|
||||
_duplicate=True,
|
||||
session_id=session_id,
|
||||
force_values=force_values,
|
||||
force_settings=force_settings,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
else:
|
||||
if session_id is None and metaconfig_prefix is not None:
|
||||
session_id = metaconfig_prefix + self.impl_getname()
|
||||
duplicated_config = KernelMetaConfig([],
|
||||
_duplicate=True,
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
duplicated_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
|
||||
properties = self.cfgimpl_get_settings()._p_.exportation()
|
||||
duplicated_config.cfgimpl_get_settings()._p_.importation(properties)
|
||||
duplicated_config.cfgimpl_get_settings()._pp_.importation(self.cfgimpl_get_settings(
|
||||
)._pp_.exportation())
|
||||
duplicated_config.cfgimpl_get_settings().ro_append = self.cfgimpl_get_settings().ro_append
|
||||
duplicated_config.cfgimpl_get_settings().rw_append = self.cfgimpl_get_settings().rw_append
|
||||
duplicated_config.cfgimpl_get_settings().ro_remove = self.cfgimpl_get_settings().ro_remove
|
||||
duplicated_config.cfgimpl_get_settings().rw_remove = self.cfgimpl_get_settings().rw_remove
|
||||
duplicated_config.cfgimpl_get_settings().default_properties = self.cfgimpl_get_settings().default_properties
|
||||
duplicated_config.cfgimpl_reset_cache(None, None)
|
||||
duplicated_config = await KernelMetaConfig([],
|
||||
_duplicate=True,
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
duplicated_values = duplicated_config.cfgimpl_get_values()
|
||||
duplicated_settings = duplicated_config.cfgimpl_get_settings()
|
||||
await duplicated_values._p_.importation(await self.cfgimpl_get_values()._p_.exportation())
|
||||
properties = await self.cfgimpl_get_settings()._p_.exportation()
|
||||
await duplicated_settings._p_.importation(properties)
|
||||
await duplicated_settings._pp_.importation(await self.cfgimpl_get_settings()._pp_.exportation())
|
||||
duplicated_settings.ro_append = self.cfgimpl_get_settings().ro_append
|
||||
duplicated_settings.rw_append = self.cfgimpl_get_settings().rw_append
|
||||
duplicated_settings.ro_remove = self.cfgimpl_get_settings().ro_remove
|
||||
duplicated_settings.rw_remove = self.cfgimpl_get_settings().rw_remove
|
||||
duplicated_settings.default_properties = self.cfgimpl_get_settings().default_properties
|
||||
await duplicated_config.cfgimpl_reset_cache(None, None)
|
||||
if child is not None:
|
||||
duplicated_config._impl_children.append(child)
|
||||
child.parents.append(weakref.ref(duplicated_config))
|
||||
@ -655,11 +685,11 @@ class _CommonConfig(SubConfig):
|
||||
wparent = parent()
|
||||
if wparent not in deep:
|
||||
deep.append(wparent)
|
||||
duplicated_config = wparent.duplicate(deep=deep,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
child=duplicated_config,
|
||||
persistent=persistent)
|
||||
duplicated_config = await wparent.duplicate(deep=deep,
|
||||
storage=storage,
|
||||
metaconfig_prefix=metaconfig_prefix,
|
||||
child=duplicated_config,
|
||||
persistent=persistent)
|
||||
else:
|
||||
duplicated_config.parents = self.parents
|
||||
for parent in self.parents:
|
||||
@ -677,6 +707,7 @@ class _CommonConfig(SubConfig):
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
@asyncinit
|
||||
class KernelConfig(_CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = ('__weakref__',
|
||||
@ -685,15 +716,15 @@ class KernelConfig(_CommonConfig):
|
||||
'_impl_symlink')
|
||||
impl_type = 'config'
|
||||
|
||||
def __init__(self,
|
||||
descr,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
force_values=None,
|
||||
force_settings=None,
|
||||
display_name=None,
|
||||
_duplicate=False,
|
||||
storage=None):
|
||||
async def __init__(self,
|
||||
descr,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
force_values=None,
|
||||
force_settings=None,
|
||||
display_name=None,
|
||||
_duplicate=False,
|
||||
storage=None):
|
||||
""" Configuration option management class
|
||||
|
||||
:param descr: describes the configuration schema
|
||||
@ -721,43 +752,45 @@ class KernelConfig(_CommonConfig):
|
||||
self._impl_settings = force_settings
|
||||
self._impl_permissives_cache = Cache()
|
||||
self._impl_properties_cache = Cache()
|
||||
self._impl_values = Values(force_values)
|
||||
self._impl_values = await Values(force_values)
|
||||
self._impl_values_cache = Cache()
|
||||
else:
|
||||
properties, permissives, values, session_id = get_storages(self,
|
||||
session_id,
|
||||
persistent,
|
||||
storage=storage)
|
||||
properties, permissives, values, session_id = await get_storages(self,
|
||||
session_id,
|
||||
persistent,
|
||||
storage=storage)
|
||||
if not valid_name(session_id):
|
||||
raise ValueError(_("invalid session ID: {0} for config").format(session_id))
|
||||
self._impl_settings = Settings(properties,
|
||||
permissives)
|
||||
self._impl_permissives_cache = Cache()
|
||||
self._impl_properties_cache = Cache()
|
||||
self._impl_values = Values(values)
|
||||
self._impl_values = await Values(values)
|
||||
self._impl_values_cache = Cache()
|
||||
super().__init__(descr,
|
||||
weakref.ref(self),
|
||||
ConfigBag(self),
|
||||
None)
|
||||
self._impl_context = weakref.ref(self)
|
||||
await super().__init__(descr,
|
||||
self._impl_context,
|
||||
None,
|
||||
None)
|
||||
if None in [force_settings, force_values]:
|
||||
self._impl_build_all_caches()
|
||||
await self._impl_build_all_caches()
|
||||
self._impl_name = session_id
|
||||
|
||||
def impl_getname(self):
|
||||
return self._impl_name
|
||||
|
||||
|
||||
@asyncinit
|
||||
class KernelGroupConfig(_CommonConfig):
|
||||
__slots__ = ('__weakref__',
|
||||
'_impl_children',
|
||||
'_impl_name')
|
||||
impl_type = 'group'
|
||||
|
||||
def __init__(self,
|
||||
children,
|
||||
session_id=None,
|
||||
_descr=None):
|
||||
async def __init__(self,
|
||||
children,
|
||||
session_id=None,
|
||||
_descr=None):
|
||||
assert isinstance(children, list), _("groupconfig's children must be a list")
|
||||
names = []
|
||||
for child in children:
|
||||
@ -775,23 +808,26 @@ class KernelGroupConfig(_CommonConfig):
|
||||
self.parents = []
|
||||
session_id = gen_storage_id(session_id, self)
|
||||
assert valid_name(session_id), _("invalid session ID: {0} for config").format(session_id)
|
||||
super().__init__(_descr,
|
||||
weakref.ref(self),
|
||||
ConfigBag(self),
|
||||
None)
|
||||
config_bag = ConfigBag(self,
|
||||
properties=None,
|
||||
permissives=None)
|
||||
await super().__init__(_descr,
|
||||
weakref.ref(self),
|
||||
config_bag,
|
||||
None)
|
||||
self._impl_name = session_id
|
||||
|
||||
def cfgimpl_get_children(self):
|
||||
return self._impl_children
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
option_bag,
|
||||
resetted_opts=None):
|
||||
async def cfgimpl_reset_cache(self,
|
||||
option_bag,
|
||||
resetted_opts=None):
|
||||
if resetted_opts is None:
|
||||
resetted_opts = []
|
||||
if isinstance(self, KernelMixConfig):
|
||||
super().cfgimpl_reset_cache(option_bag,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
await super().cfgimpl_reset_cache(option_bag,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
for child in self._impl_children:
|
||||
if option_bag is not None:
|
||||
coption_bag = option_bag.copy()
|
||||
@ -800,16 +836,16 @@ class KernelGroupConfig(_CommonConfig):
|
||||
coption_bag.config_bag = cconfig_bag
|
||||
else:
|
||||
coption_bag = None
|
||||
child.cfgimpl_reset_cache(coption_bag,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
await child.cfgimpl_reset_cache(coption_bag,
|
||||
resetted_opts=copy(resetted_opts))
|
||||
|
||||
def set_value(self,
|
||||
path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
only_config=False,
|
||||
_commit=True):
|
||||
async def set_value(self,
|
||||
path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
only_config=False,
|
||||
_commit=True):
|
||||
"""Setattr not in current KernelGroupConfig, but in each children
|
||||
"""
|
||||
ret = []
|
||||
@ -823,27 +859,33 @@ class KernelGroupConfig(_CommonConfig):
|
||||
cconfig_bag = config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
if isinstance(child, KernelGroupConfig):
|
||||
ret.extend(child.set_value(path,
|
||||
index,
|
||||
value,
|
||||
cconfig_bag,
|
||||
only_config=only_config,
|
||||
_commit=commit))
|
||||
ret.extend(await child.set_value(path,
|
||||
index,
|
||||
value,
|
||||
cconfig_bag,
|
||||
only_config=only_config,
|
||||
_commit=commit))
|
||||
else:
|
||||
settings = child.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(child._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
try:
|
||||
subconfig, name = child.cfgimpl_get_home_by_path(path,
|
||||
cconfig_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
cconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
subconfig, name = await child.cfgimpl_get_home_by_path(path,
|
||||
cconfig_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
cconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
index,
|
||||
cconfig_bag)
|
||||
child.setattr(value,
|
||||
option_bag,
|
||||
_commit=commit)
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
await child.setattr(value,
|
||||
option_bag,
|
||||
_commit=commit)
|
||||
except PropertiesOptionError as err:
|
||||
ret.append(PropertiesOptionError(err._option_bag,
|
||||
err.proptype,
|
||||
@ -854,18 +896,18 @@ class KernelGroupConfig(_CommonConfig):
|
||||
except (ValueError, LeadershipError, AttributeError) as err:
|
||||
ret.append(err)
|
||||
if _commit and self.impl_type != 'group':
|
||||
self.cfgimpl_get_values()._p_.commit()
|
||||
await self.cfgimpl_get_values()._p_.commit()
|
||||
return ret
|
||||
|
||||
|
||||
def find_group(self,
|
||||
config_bag,
|
||||
byname=None,
|
||||
bypath=undefined,
|
||||
byoption=undefined,
|
||||
byvalue=undefined,
|
||||
raise_if_not_found=True,
|
||||
_sub=False):
|
||||
async def find_group(self,
|
||||
config_bag,
|
||||
byname=None,
|
||||
bypath=undefined,
|
||||
byoption=undefined,
|
||||
byvalue=undefined,
|
||||
raise_if_not_found=True,
|
||||
_sub=False):
|
||||
"""Find first not in current KernelGroupConfig, but in each children
|
||||
"""
|
||||
# if KernelMetaConfig, all children have same OptionDescription in
|
||||
@ -873,38 +915,42 @@ class KernelGroupConfig(_CommonConfig):
|
||||
if bypath is undefined and byname is not None and \
|
||||
isinstance(self,
|
||||
KernelMixConfig):
|
||||
bypath, byoption = next(self.find(bytype=None,
|
||||
byvalue=undefined,
|
||||
byname=byname,
|
||||
config_bag=config_bag,
|
||||
raise_if_not_found=raise_if_not_found,
|
||||
with_option=True))
|
||||
async for bypath, byoption in self.find(bytype=None,
|
||||
byvalue=undefined,
|
||||
byname=byname,
|
||||
config_bag=config_bag,
|
||||
raise_if_not_found=raise_if_not_found,
|
||||
with_option=True):
|
||||
break
|
||||
byname = None
|
||||
|
||||
ret = []
|
||||
for child in self._impl_children:
|
||||
if isinstance(child, KernelGroupConfig):
|
||||
ret.extend(child.find_group(byname=byname,
|
||||
bypath=bypath,
|
||||
byoption=byoption,
|
||||
byvalue=byvalue,
|
||||
config_bag=config_bag,
|
||||
raise_if_not_found=False,
|
||||
_sub=True))
|
||||
ret.extend(await child.find_group(byname=byname,
|
||||
bypath=bypath,
|
||||
byoption=byoption,
|
||||
byvalue=byvalue,
|
||||
config_bag=config_bag,
|
||||
raise_if_not_found=False,
|
||||
_sub=True))
|
||||
else:
|
||||
try:
|
||||
cconfig_bag = config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
next(child.find(None,
|
||||
byname,
|
||||
byvalue,
|
||||
config_bag=cconfig_bag,
|
||||
raise_if_not_found=False,
|
||||
only_path=bypath,
|
||||
only_option=byoption))
|
||||
cconfig_bag = config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
settings = child.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(child._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
async for path in child.find(None,
|
||||
byname,
|
||||
byvalue,
|
||||
config_bag=cconfig_bag,
|
||||
raise_if_not_found=False,
|
||||
only_path=bypath,
|
||||
only_option=byoption):
|
||||
ret.append(child)
|
||||
except StopIteration:
|
||||
pass
|
||||
break
|
||||
if not _sub:
|
||||
self._find_return_results(ret != [],
|
||||
raise_if_not_found)
|
||||
@ -913,25 +959,31 @@ class KernelGroupConfig(_CommonConfig):
|
||||
def impl_getname(self):
|
||||
return self._impl_name
|
||||
|
||||
def reset(self,
|
||||
path,
|
||||
_commit=True):
|
||||
async def reset(self,
|
||||
path,
|
||||
_commit=True):
|
||||
for child in self._impl_children:
|
||||
config_bag = ConfigBag(child)
|
||||
settings = child.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(child._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
config_bag = ConfigBag(child,
|
||||
properties=properties,
|
||||
permissives=permissives)
|
||||
config_bag.remove_validation()
|
||||
subconfig, name = child.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
subconfig, name = await child.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
option,
|
||||
None,
|
||||
config_bag)
|
||||
option_bag.properties = await child.cfgimpl_get_settings().getproperties(option_bag)
|
||||
option_bag.config_bag.context = child
|
||||
child.cfgimpl_get_values().reset(option_bag,
|
||||
_commit=_commit)
|
||||
await child.cfgimpl_get_values().reset(option_bag,
|
||||
_commit=_commit)
|
||||
|
||||
def getconfig(self,
|
||||
name):
|
||||
@ -941,19 +993,20 @@ class KernelGroupConfig(_CommonConfig):
|
||||
raise ConfigError(_('unknown config "{}"').format(name))
|
||||
|
||||
|
||||
@asyncinit
|
||||
class KernelMixConfig(KernelGroupConfig):
|
||||
__slots__ = ('_display_name',
|
||||
'_impl_symlink')
|
||||
impl_type = 'mix'
|
||||
|
||||
def __init__(self,
|
||||
optiondescription,
|
||||
children,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
display_name=None,
|
||||
_duplicate=False):
|
||||
async def __init__(self,
|
||||
optiondescription,
|
||||
children,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
storage=None,
|
||||
display_name=None,
|
||||
_duplicate=False):
|
||||
# FIXME _duplicate
|
||||
self._display_name = display_name
|
||||
self._impl_symlink = []
|
||||
@ -961,31 +1014,31 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
if not isinstance(child, (KernelConfig, KernelMixConfig)):
|
||||
raise TypeError(_("child must be a Config, MixConfig or MetaConfig"))
|
||||
child.parents.append(weakref.ref(self))
|
||||
properties, permissives, values, session_id = get_storages(self,
|
||||
session_id,
|
||||
persistent,
|
||||
storage=storage)
|
||||
properties, permissives, values, session_id = await get_storages(self,
|
||||
session_id,
|
||||
persistent,
|
||||
storage=storage)
|
||||
self._impl_settings = Settings(properties,
|
||||
permissives)
|
||||
self._impl_permissives_cache = Cache()
|
||||
self._impl_properties_cache = Cache()
|
||||
self._impl_values = Values(values)
|
||||
self._impl_values = await Values(values)
|
||||
self._impl_values_cache = Cache()
|
||||
super().__init__(children,
|
||||
session_id=session_id,
|
||||
_descr=optiondescription)
|
||||
self._impl_build_all_caches()
|
||||
await super().__init__(children,
|
||||
session_id=session_id,
|
||||
_descr=optiondescription)
|
||||
await self._impl_build_all_caches()
|
||||
|
||||
def set_value(self,
|
||||
path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
force_default=False,
|
||||
force_dont_change_value=False,
|
||||
force_default_if_same=False,
|
||||
only_config=False,
|
||||
_commit=True):
|
||||
async def set_value(self,
|
||||
path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
force_default=False,
|
||||
force_dont_change_value=False,
|
||||
force_default_if_same=False,
|
||||
only_config=False,
|
||||
_commit=True):
|
||||
"""only_config: could be set if you want modify value in all Config included in
|
||||
this KernelMetaConfig
|
||||
"""
|
||||
@ -994,23 +1047,24 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
raise ValueError(_('force_default, force_default_if_same or '
|
||||
'force_dont_change_value cannot be set with'
|
||||
' only_config'))
|
||||
return super().set_value(path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
only_config=only_config,
|
||||
_commit=_commit)
|
||||
return await super().set_value(path,
|
||||
index,
|
||||
value,
|
||||
config_bag,
|
||||
only_config=only_config,
|
||||
_commit=_commit)
|
||||
ret = []
|
||||
subconfig, name = self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
self.cfgimpl_get_path())
|
||||
subconfig, name = await self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
self.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
index,
|
||||
config_bag)
|
||||
option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag)
|
||||
if force_default or force_default_if_same or force_dont_change_value:
|
||||
if force_default and force_dont_change_value:
|
||||
raise ValueError(_('force_default and force_dont_change_value'
|
||||
@ -1018,40 +1072,48 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
for child in self._impl_children:
|
||||
cconfig_bag = config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
settings = child.cfgimpl_get_settings()
|
||||
properties = await settings.get_context_properties(child._impl_properties_cache)
|
||||
permissives = await settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
try:
|
||||
subconfig2, name = child.cfgimpl_get_home_by_path(path,
|
||||
cconfig_bag)
|
||||
subconfig2, name = await child.cfgimpl_get_home_by_path(path,
|
||||
cconfig_bag)
|
||||
if self.impl_type == 'meta':
|
||||
moption_bag = option_bag
|
||||
moption_bag = option_bag.copy()
|
||||
del moption_bag.properties
|
||||
del moption_bag.permissives
|
||||
|
||||
moption_bag.config_bag = cconfig_bag
|
||||
moption_bag.properties = await settings.getproperties(moption_bag)
|
||||
else:
|
||||
option = subconfig2.cfgimpl_get_description().get_child(name,
|
||||
cconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
option = await subconfig2.cfgimpl_get_description().get_child(name,
|
||||
cconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
moption_bag = OptionBag()
|
||||
moption_bag.set_option(option,
|
||||
path,
|
||||
index,
|
||||
cconfig_bag)
|
||||
moption_bag.properties = await settings.getproperties(moption_bag)
|
||||
if force_default_if_same:
|
||||
if not child.cfgimpl_get_values()._p_.hasvalue(path):
|
||||
if not await child.cfgimpl_get_values()._p_.hasvalue(path):
|
||||
child_value = undefined
|
||||
else:
|
||||
child_value = subconfig2.getattr(name,
|
||||
moption_bag)
|
||||
child_value = await subconfig2.getattr(name,
|
||||
moption_bag)
|
||||
if force_default or (force_default_if_same and value == child_value):
|
||||
child.cfgimpl_get_values().reset(moption_bag,
|
||||
_commit=False)
|
||||
await child.cfgimpl_get_values().reset(moption_bag,
|
||||
_commit=False)
|
||||
continue
|
||||
if force_dont_change_value:
|
||||
child_value = child.getattr(name,
|
||||
moption_bag)
|
||||
child_value = await child.getattr(name,
|
||||
moption_bag)
|
||||
if value != child_value:
|
||||
subconfig2.setattr(child_value,
|
||||
moption_bag,
|
||||
_commit=False)
|
||||
await subconfig2.setattr(child_value,
|
||||
moption_bag,
|
||||
_commit=False)
|
||||
except PropertiesOptionError as err:
|
||||
ret.append(PropertiesOptionError(err._option_bag,
|
||||
err.proptype,
|
||||
@ -1064,46 +1126,52 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
|
||||
try:
|
||||
if self.impl_type == 'meta':
|
||||
del option_bag.properties
|
||||
del option_bag.permissives
|
||||
option_bag.config_bag = config_bag
|
||||
subconfig.setattr(value,
|
||||
option_bag,
|
||||
_commit=False)
|
||||
moption_bag = option_bag.copy()
|
||||
#del option_bag.properties
|
||||
#del option_bag.permissives
|
||||
moption_bag.config_bag = config_bag
|
||||
moption_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(moption_bag)
|
||||
else:
|
||||
moption_bag = option_bag
|
||||
await subconfig.setattr(value,
|
||||
moption_bag,
|
||||
_commit=False)
|
||||
except (PropertiesOptionError, ValueError, LeadershipError) as err:
|
||||
ret.append(err)
|
||||
return ret
|
||||
|
||||
def reset(self,
|
||||
path,
|
||||
only_children,
|
||||
config_bag,
|
||||
commit=True):
|
||||
async def reset(self,
|
||||
path,
|
||||
only_children,
|
||||
config_bag,
|
||||
commit=True):
|
||||
rconfig_bag = config_bag.copy()
|
||||
rconfig_bag.remove_validation()
|
||||
if self.impl_type == 'meta':
|
||||
subconfig, name = self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
subconfig, name = await self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
None,
|
||||
rconfig_bag)
|
||||
option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag)
|
||||
elif not only_children:
|
||||
try:
|
||||
subconfig, name = self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
subconfig, name = await self.cfgimpl_get_home_by_path(path,
|
||||
config_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
config_bag,
|
||||
subconfig.cfgimpl_get_path())
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
path,
|
||||
None,
|
||||
rconfig_bag)
|
||||
option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag)
|
||||
except AttributeError:
|
||||
only_children = True
|
||||
for child in self._impl_children:
|
||||
@ -1113,34 +1181,35 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
moption_bag = option_bag
|
||||
moption_bag.config_bag = rconfig_bag
|
||||
else:
|
||||
subconfig, name = child.cfgimpl_get_home_by_path(path,
|
||||
rconfig_bag)
|
||||
option = subconfig.cfgimpl_get_description().get_child(name,
|
||||
rconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
subconfig, name = await child.cfgimpl_get_home_by_path(path,
|
||||
rconfig_bag)
|
||||
option = await subconfig.cfgimpl_get_description().get_child(name,
|
||||
rconfig_bag,
|
||||
child.cfgimpl_get_path())
|
||||
moption_bag = OptionBag()
|
||||
moption_bag.set_option(option,
|
||||
path,
|
||||
None,
|
||||
rconfig_bag)
|
||||
child.cfgimpl_get_values().reset(moption_bag,
|
||||
_commit=False)
|
||||
moption_bag.properties = await self.cfgimpl_get_settings().getproperties(moption_bag)
|
||||
await child.cfgimpl_get_values().reset(moption_bag,
|
||||
_commit=False)
|
||||
except AttributeError:
|
||||
pass
|
||||
if isinstance(child, KernelMixConfig):
|
||||
child.reset(path,
|
||||
False,
|
||||
rconfig_bag,
|
||||
commit=False)
|
||||
await child.reset(path,
|
||||
False,
|
||||
rconfig_bag,
|
||||
commit=False)
|
||||
if not only_children:
|
||||
option_bag.config_bag = config_bag
|
||||
self.cfgimpl_get_values().reset(option_bag,
|
||||
_commit=False)
|
||||
await self.cfgimpl_get_values().reset(option_bag,
|
||||
_commit=False)
|
||||
if commit:
|
||||
self.cfgimpl_get_values()._p_.commit()
|
||||
await self.cfgimpl_get_values()._p_.commit()
|
||||
|
||||
def add_config(self,
|
||||
apiconfig):
|
||||
async def add_config(self,
|
||||
apiconfig):
|
||||
config = apiconfig._config_bag.context
|
||||
if config.impl_getname() in [child.impl_getname() for child in self._impl_children]:
|
||||
raise ConflictError(_('config name must be uniq in '
|
||||
@ -1148,15 +1217,15 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
|
||||
config.parents.append(weakref.ref(self))
|
||||
self._impl_children.append(config)
|
||||
config.cfgimpl_reset_cache(None, None)
|
||||
await config.cfgimpl_reset_cache(None, None)
|
||||
|
||||
def pop_config(self,
|
||||
session_id,
|
||||
config):
|
||||
async def pop_config(self,
|
||||
session_id,
|
||||
config):
|
||||
if session_id is not None:
|
||||
for idx, child in enumerate(self._impl_children):
|
||||
if session_id == child.impl_getname():
|
||||
child.cfgimpl_reset_cache(None, None)
|
||||
await child.cfgimpl_reset_cache(None, None)
|
||||
self._impl_children.pop(idx)
|
||||
break
|
||||
else:
|
||||
@ -1173,18 +1242,19 @@ class KernelMixConfig(KernelGroupConfig):
|
||||
return child
|
||||
|
||||
|
||||
@asyncinit
|
||||
class KernelMetaConfig(KernelMixConfig):
|
||||
__slots__ = tuple()
|
||||
impl_type = 'meta'
|
||||
|
||||
def __init__(self,
|
||||
children,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
optiondescription=None,
|
||||
storage=None,
|
||||
display_name=None,
|
||||
_duplicate=False):
|
||||
async def __init__(self,
|
||||
children,
|
||||
session_id=None,
|
||||
persistent=False,
|
||||
optiondescription=None,
|
||||
storage=None,
|
||||
display_name=None,
|
||||
_duplicate=False):
|
||||
descr = None
|
||||
self._display_name = display_name
|
||||
if optiondescription is not None:
|
||||
@ -1194,10 +1264,10 @@ class KernelMetaConfig(KernelMixConfig):
|
||||
assert isinstance(child_session_id, str), _('MetaConfig with optiondescription'
|
||||
' must have string has child, '
|
||||
'not {}').format(child_session_id)
|
||||
new_children.append(KernelConfig(optiondescription,
|
||||
persistent=persistent,
|
||||
session_id=child_session_id,
|
||||
display_name=self._display_name))
|
||||
new_children.append(await KernelConfig(optiondescription,
|
||||
persistent=persistent,
|
||||
session_id=child_session_id,
|
||||
display_name=self._display_name))
|
||||
children = new_children
|
||||
descr = optiondescription
|
||||
for child in children:
|
||||
@ -1209,59 +1279,61 @@ class KernelMetaConfig(KernelMixConfig):
|
||||
elif descr is not child.cfgimpl_get_description():
|
||||
raise ValueError(_('all config in metaconfig must '
|
||||
'have the same optiondescription'))
|
||||
super().__init__(descr,
|
||||
children,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
session_id=session_id)
|
||||
await super().__init__(descr,
|
||||
children,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
session_id=session_id)
|
||||
|
||||
def new_config(self,
|
||||
session_id,
|
||||
type_='config',
|
||||
persistent=False,
|
||||
storage=None):
|
||||
async def new_config(self,
|
||||
session_id,
|
||||
type_='config',
|
||||
persistent=False,
|
||||
storage=None):
|
||||
if session_id in [child.impl_getname() for child in self._impl_children]:
|
||||
raise ConflictError(_('config name must be uniq in '
|
||||
'groupconfig for {0}').format(session_id))
|
||||
assert type_ in ('config', 'metaconfig', 'mixconfig'), _('unknown type {}').format(type_)
|
||||
new = not persistent or session_id not in list_sessions()
|
||||
if type_ == 'config':
|
||||
config = KernelConfig(self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
config = await KernelConfig(self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
elif type_ == 'metaconfig':
|
||||
config = KernelMetaConfig([],
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
config = await KernelMetaConfig([],
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
elif type_ == 'mixconfig':
|
||||
config = KernelMixConfig(children=[],
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
config = await KernelMixConfig(children=[],
|
||||
optiondescription=self._impl_descr,
|
||||
session_id=session_id,
|
||||
persistent=persistent,
|
||||
storage=storage,
|
||||
display_name=self._display_name)
|
||||
# Copy context properties/permissives
|
||||
if new:
|
||||
config.cfgimpl_get_settings().set_context_properties(self.cfgimpl_get_settings().get_context_properties(config._impl_properties_cache), config)
|
||||
config.cfgimpl_get_settings().set_context_permissives(self.cfgimpl_get_settings().get_context_permissives())
|
||||
config.cfgimpl_get_settings().ro_append = self.cfgimpl_get_settings().ro_append
|
||||
config.cfgimpl_get_settings().rw_append = self.cfgimpl_get_settings().rw_append
|
||||
config.cfgimpl_get_settings().ro_remove = self.cfgimpl_get_settings().ro_remove
|
||||
config.cfgimpl_get_settings().rw_remove = self.cfgimpl_get_settings().rw_remove
|
||||
config.cfgimpl_get_settings().default_properties = self.cfgimpl_get_settings().default_properties
|
||||
settings = config.cfgimpl_get_settings()
|
||||
properties = await self.cfgimpl_get_settings().get_context_properties(config._impl_properties_cache)
|
||||
await settings.set_context_properties(properties, config)
|
||||
await settings.set_context_permissives(await self.cfgimpl_get_settings().get_context_permissives())
|
||||
settings.ro_append = self.cfgimpl_get_settings().ro_append
|
||||
settings.rw_append = self.cfgimpl_get_settings().rw_append
|
||||
settings.ro_remove = self.cfgimpl_get_settings().ro_remove
|
||||
settings.rw_remove = self.cfgimpl_get_settings().rw_remove
|
||||
settings.default_properties = self.cfgimpl_get_settings().default_properties
|
||||
|
||||
config.parents.append(weakref.ref(self))
|
||||
self._impl_children.append(config)
|
||||
return config
|
||||
|
||||
def add_config(self,
|
||||
apiconfig):
|
||||
async def add_config(self,
|
||||
apiconfig):
|
||||
if self._impl_descr is not apiconfig._config_bag.context.cfgimpl_get_description():
|
||||
raise ValueError(_('metaconfig must '
|
||||
'have the same optiondescription'))
|
||||
super().add_config(apiconfig)
|
||||
await super().add_config(apiconfig)
|
||||
|
@ -84,16 +84,12 @@ class PropertiesOptionError(AttributeError):
|
||||
return self.msg
|
||||
if self._settings is None:
|
||||
return 'error'
|
||||
properties = list(self._settings.calc_raises_properties(self._option_bag,
|
||||
apply_requires=False))
|
||||
for property_ in self._settings.get_calculated_properties(self._option_bag):
|
||||
prop = property_.help(self._option_bag)
|
||||
if prop is not None:
|
||||
properties.append(prop)
|
||||
#for property_ in self._settings.get_calculated_properties(self._option_bag):
|
||||
# prop = property_.help(self._option_bag)
|
||||
# if prop is not None:
|
||||
# properties.append(prop)
|
||||
|
||||
if not properties:
|
||||
# if proptype == ['mandatory']
|
||||
properties = self.proptype
|
||||
properties = list(self.proptype)
|
||||
only_one = len(properties) == 1
|
||||
properties_msg = display_list(properties, add_quote=True)
|
||||
if only_one:
|
||||
|
@ -29,7 +29,7 @@ from ..i18n import _
|
||||
from ..setting import undefined, Settings
|
||||
from ..value import Values
|
||||
from ..error import ConfigError, display_list
|
||||
from ..autolib import Calculation, Params, ParamContext, ParamOption, ParamIndex
|
||||
from ..autolib import Calculation, Params, ParamOption, ParamIndex
|
||||
|
||||
STATIC_TUPLE = frozenset()
|
||||
|
||||
@ -55,7 +55,6 @@ class Base:
|
||||
'_properties',
|
||||
'_has_dependency',
|
||||
'_dependencies',
|
||||
'_has_calc_context',
|
||||
'__weakref__'
|
||||
)
|
||||
|
||||
|
@ -50,15 +50,15 @@ class ChoiceOption(Option):
|
||||
raise TypeError(_('values must be a tuple or a calculation for {0}'
|
||||
).format(name))
|
||||
self._choice_values = values
|
||||
super(ChoiceOption, self).__init__(name,
|
||||
doc,
|
||||
*args,
|
||||
**kwargs)
|
||||
super().__init__(name,
|
||||
doc,
|
||||
*args,
|
||||
**kwargs)
|
||||
|
||||
def impl_get_values(self,
|
||||
option_bag):
|
||||
async def impl_get_values(self,
|
||||
option_bag):
|
||||
if isinstance(self._choice_values, Calculation):
|
||||
values = self._choice_values.execute(option_bag)
|
||||
values = await self._choice_values.execute(option_bag)
|
||||
if values is not undefined and not isinstance(values, list):
|
||||
raise ConfigError(_('calculated values for {0} is not a list'
|
||||
'').format(self.impl_getname()))
|
||||
@ -70,10 +70,23 @@ class ChoiceOption(Option):
|
||||
value: Any) -> None:
|
||||
pass
|
||||
|
||||
def validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
values = self.impl_get_values(option_bag)
|
||||
def sync_validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
if isinstance(self._choice_values, Calculation):
|
||||
return
|
||||
values = self._choice_values
|
||||
if values is not undefined and value not in values:
|
||||
if len(values) == 1:
|
||||
raise ValueError(_('only "{0}" is allowed'
|
||||
'').format(values[0]))
|
||||
raise ValueError(_('only {0} are allowed'
|
||||
'').format(display_list(values, add_quote=True)))
|
||||
|
||||
async def validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
values = await self.impl_get_values(option_bag)
|
||||
if values is not undefined and value not in values:
|
||||
if len(values) == 1:
|
||||
raise ValueError(_('only "{0}" is allowed'
|
||||
|
@ -83,6 +83,10 @@ class DomainnameOption(StrOption):
|
||||
if allow_ip:
|
||||
msg = _('could be a IP, otherwise {}').format(msg)
|
||||
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
||||
if not allow_cidr_network:
|
||||
regexp = r'(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))'.format(regexp)
|
||||
else:
|
||||
regexp = r'(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[0-9][0-9]))'.format(regexp)
|
||||
regexp = r'^{0}$'.format(regexp)
|
||||
extra['_domain_re'] = re.compile(regexp)
|
||||
extra['_domain_re_message'] = msg
|
||||
|
@ -27,7 +27,7 @@ from .optiondescription import OptionDescription
|
||||
from .baseoption import BaseOption
|
||||
from ..setting import OptionBag, ConfigBag, groups, undefined
|
||||
from ..error import ConfigError
|
||||
from ..autolib import carry_out_calculation, Calculation
|
||||
from ..autolib import Calculation
|
||||
|
||||
|
||||
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
|
||||
@ -53,7 +53,7 @@ class DynOptionDescription(OptionDescription):
|
||||
if __debug__ and child.impl_get_group_type() != groups.leadership:
|
||||
raise ConfigError(_('cannot set optiondescription in a '
|
||||
'dynoptiondescription'))
|
||||
for chld in child.get_children(config_bag=undefined):
|
||||
for chld in child._children[1]:
|
||||
chld._setsubdyn(self)
|
||||
if __debug__ and child.impl_is_symlinkoption():
|
||||
raise ConfigError(_('cannot set symlinkoption in a '
|
||||
@ -67,15 +67,14 @@ class DynOptionDescription(OptionDescription):
|
||||
suffix):
|
||||
return suffix
|
||||
|
||||
def get_suffixes(self,
|
||||
config_bag: ConfigBag) -> List[str]:
|
||||
|
||||
async def get_suffixes(self,
|
||||
config_bag: ConfigBag) -> List[str]:
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(self,
|
||||
self.impl_getpath(),
|
||||
None,
|
||||
config_bag)
|
||||
values = self._suffixes.execute(option_bag)
|
||||
values = await self._suffixes.execute(option_bag)
|
||||
if __debug__:
|
||||
if not isinstance(values, list):
|
||||
raise ValueError(_('DynOptionDescription suffixes for option "{}", is not a list ({})'
|
||||
|
@ -111,10 +111,10 @@ class Leadership(OptionDescription):
|
||||
opt = opt.opt
|
||||
return opt in self._children[1]
|
||||
|
||||
def reset(self,
|
||||
values: Values,
|
||||
option_bag: OptionBag,
|
||||
_commit: bool=True) -> None:
|
||||
async def reset(self,
|
||||
values: Values,
|
||||
option_bag: OptionBag,
|
||||
_commit: bool=True) -> None:
|
||||
config_bag = option_bag.config_bag.copy()
|
||||
config_bag.remove_validation()
|
||||
for follower in self.get_followers():
|
||||
@ -124,41 +124,43 @@ class Leadership(OptionDescription):
|
||||
follower_path,
|
||||
None,
|
||||
config_bag)
|
||||
values.reset(soption_bag,
|
||||
_commit=_commit)
|
||||
soption_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(soption_bag)
|
||||
await values.reset(soption_bag,
|
||||
_commit=_commit)
|
||||
|
||||
def follower_force_store_value(self,
|
||||
values,
|
||||
value,
|
||||
option_bag,
|
||||
owner,
|
||||
_commit) -> None:
|
||||
async def follower_force_store_value(self,
|
||||
values,
|
||||
value,
|
||||
option_bag,
|
||||
owner,
|
||||
_commit) -> None:
|
||||
settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
if value:
|
||||
rgevalue = range(len(value))
|
||||
for follower in self.get_children(option_bag.config_bag):
|
||||
for follower in await self.get_children(option_bag.config_bag):
|
||||
foption_bag = OptionBag()
|
||||
foption_bag.set_option(follower,
|
||||
follower.impl_getpath(),
|
||||
None,
|
||||
option_bag.config_bag)
|
||||
if 'force_store_value' in settings.getproperties(foption_bag):
|
||||
if 'force_store_value' in await settings.getproperties(foption_bag):
|
||||
for index in rgevalue:
|
||||
foption_bag = OptionBag()
|
||||
foption_bag.set_option(follower,
|
||||
follower.impl_getpath(),
|
||||
index,
|
||||
option_bag.config_bag)
|
||||
values._setvalue(foption_bag,
|
||||
values.getvalue(foption_bag),
|
||||
owner,
|
||||
commit=False)
|
||||
foption_bag.properties = await settings.getproperties(foption_bag)
|
||||
await values._setvalue(foption_bag,
|
||||
await values.getvalue(foption_bag),
|
||||
owner,
|
||||
commit=False)
|
||||
|
||||
def pop(self,
|
||||
values: Values,
|
||||
index: int,
|
||||
option_bag: OptionBag,
|
||||
followers: Optional[List[Option]]=undefined) -> None:
|
||||
async def pop(self,
|
||||
values: Values,
|
||||
index: int,
|
||||
option_bag: OptionBag,
|
||||
followers: Optional[List[Option]]=undefined) -> None:
|
||||
if followers is undefined:
|
||||
# followers are not undefined only in SynDynLeadership
|
||||
followers = self.get_followers()
|
||||
@ -166,7 +168,7 @@ class Leadership(OptionDescription):
|
||||
config_bag.remove_validation()
|
||||
for follower in followers:
|
||||
follower_path = follower.impl_getpath()
|
||||
followerlen = values._p_.get_max_length(follower_path)
|
||||
followerlen = await values._p_.get_max_length(follower_path)
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(follower,
|
||||
follower_path,
|
||||
@ -174,16 +176,17 @@ class Leadership(OptionDescription):
|
||||
config_bag)
|
||||
# do not check force_default_on_freeze or force_metaconfig_on_freeze
|
||||
soption_bag.properties = set()
|
||||
if not values.is_default_owner(soption_bag,
|
||||
validate_meta=False) and followerlen > index:
|
||||
values._p_.resetvalue_index(follower_path,
|
||||
index,
|
||||
True)
|
||||
is_default = await values.is_default_owner(soption_bag,
|
||||
validate_meta=False)
|
||||
if not is_default and followerlen > index:
|
||||
await values._p_.resetvalue_index(follower_path,
|
||||
index,
|
||||
True)
|
||||
if followerlen > index + 1:
|
||||
for idx in range(index + 1, followerlen):
|
||||
if values._p_.hasvalue(follower_path, idx):
|
||||
values._p_.reduce_index(follower_path,
|
||||
idx)
|
||||
if await values._p_.hasvalue(follower_path, idx):
|
||||
await values._p_.reduce_index(follower_path,
|
||||
idx)
|
||||
|
||||
def reset_cache(self,
|
||||
path: str,
|
||||
@ -212,7 +215,8 @@ class Leadership(OptionDescription):
|
||||
follower.reset_cache(spath,
|
||||
config_bag,
|
||||
None)
|
||||
resetted_opts.append(spath)
|
||||
# do not reset dependencies option
|
||||
# resetted_opts.append(spath)
|
||||
|
||||
def impl_is_leadership(self) -> None:
|
||||
return True
|
||||
|
@ -27,7 +27,7 @@ from itertools import chain
|
||||
from .baseoption import BaseOption, submulti, STATIC_TUPLE
|
||||
from ..i18n import _
|
||||
from ..setting import undefined, OptionBag, Undefined
|
||||
from ..autolib import Calculation, Params, ParamValue, ParamContext, ParamOption
|
||||
from ..autolib import Calculation, Params, ParamValue, ParamOption
|
||||
from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError,
|
||||
ValueOptionError, display_list)
|
||||
from .syndynoption import SynDynOption
|
||||
@ -101,9 +101,7 @@ class Option(BaseOption):
|
||||
if not isinstance(validator, Calculation):
|
||||
raise ValueError(_('validators must be a Calculation for "{}"').format(name))
|
||||
for param in chain(validator.params.args, validator.params.kwargs.values()):
|
||||
if isinstance(param, ParamContext):
|
||||
self._has_calc_context = True
|
||||
elif isinstance(param, ParamOption):
|
||||
if isinstance(param, ParamOption):
|
||||
param.option._add_dependency(self)
|
||||
self._has_dependency = True
|
||||
|
||||
@ -123,8 +121,8 @@ class Option(BaseOption):
|
||||
undefined)
|
||||
try:
|
||||
self.validate(value)
|
||||
self.validate_with_option(value,
|
||||
option_bag)
|
||||
self.sync_validate_with_option(value,
|
||||
option_bag)
|
||||
except ValueError as err:
|
||||
str_err = str(err)
|
||||
if not str_err:
|
||||
@ -153,11 +151,11 @@ class Option(BaseOption):
|
||||
undefined,
|
||||
None,
|
||||
undefined)
|
||||
self.impl_validate(default,
|
||||
option_bag)
|
||||
self.impl_validate(default,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
self.sync_impl_validate(default,
|
||||
option_bag)
|
||||
self.sync_impl_validate(default,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
self.value_dependencies(default)
|
||||
if (is_multi and default != []) or \
|
||||
(not is_multi and default is not None):
|
||||
@ -179,9 +177,7 @@ class Option(BaseOption):
|
||||
def value_dependency(self,
|
||||
value: Any) -> Any:
|
||||
for param in chain(value.params.args, value.params.kwargs.values()):
|
||||
if isinstance(param, ParamContext):
|
||||
self._has_calc_context = True
|
||||
elif isinstance(param, ParamOption):
|
||||
if isinstance(param, ParamOption):
|
||||
param.option._add_dependency(self)
|
||||
|
||||
#__________________________________________________________________________
|
||||
@ -237,11 +233,82 @@ class Option(BaseOption):
|
||||
|
||||
#__________________________________________________________________________
|
||||
# validator
|
||||
def sync_impl_validate(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag,
|
||||
check_error: bool=True) -> None:
|
||||
"""
|
||||
"""
|
||||
is_warnings_only = getattr(self, '_warnings_only', False)
|
||||
|
||||
def impl_validate(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag,
|
||||
check_error: bool=True) -> None:
|
||||
def do_validation(_value,
|
||||
_index):
|
||||
if isinstance(_value, list):
|
||||
raise ValueError(_('which must not be a list').format(_value,
|
||||
self.impl_get_display_name()))
|
||||
if _value is not None:
|
||||
if check_error:
|
||||
# option validation
|
||||
self.validate(_value)
|
||||
self.sync_validate_with_option(_value,
|
||||
option_bag)
|
||||
if ((check_error and not is_warnings_only) or
|
||||
(not check_error and is_warnings_only)):
|
||||
try:
|
||||
self.second_level_validation(_value,
|
||||
is_warnings_only)
|
||||
except ValueError as err:
|
||||
if is_warnings_only:
|
||||
warnings.warn_explicit(ValueWarning(_value,
|
||||
self._display_name,
|
||||
self,
|
||||
'{0}'.format(err),
|
||||
_index),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
else:
|
||||
raise err
|
||||
try:
|
||||
if isinstance(value, Calculation):
|
||||
pass
|
||||
elif not self.impl_is_multi():
|
||||
val = value
|
||||
err_index = None
|
||||
do_validation(val, None)
|
||||
elif self.impl_is_submulti():
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('which must be a list'))
|
||||
for err_index, lval in enumerate(value):
|
||||
if isinstance(lval, Calculation):
|
||||
continue
|
||||
if not isinstance(lval, list):
|
||||
raise ValueError(_('which "{}" must be a list of list'
|
||||
'').format(lval))
|
||||
for val in lval:
|
||||
if isinstance(val, Calculation):
|
||||
continue
|
||||
do_validation(val,
|
||||
err_index)
|
||||
else:
|
||||
# it's a multi
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('which must be a list'))
|
||||
for err_index, val in enumerate(value):
|
||||
if isinstance(val, Calculation):
|
||||
continue
|
||||
do_validation(val,
|
||||
err_index)
|
||||
except ValueError as err:
|
||||
raise ValueOptionError(val,
|
||||
self._display_name,
|
||||
option_bag.ori_option,
|
||||
'{0}'.format(err),
|
||||
err_index)
|
||||
|
||||
async def impl_validate(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag,
|
||||
check_error: bool=True) -> None:
|
||||
"""
|
||||
"""
|
||||
config_bag = option_bag.config_bag
|
||||
@ -264,8 +331,8 @@ class Option(BaseOption):
|
||||
raise ValueError(_('the value "{}" is not unique'
|
||||
'').format(val))
|
||||
|
||||
def calculation_validator(val,
|
||||
_index):
|
||||
async def calculation_validator(val,
|
||||
_index):
|
||||
for validator in getattr(self, '_validators', []):
|
||||
calc_is_warnings_only = hasattr(validator, 'warnings_only') and validator.warnings_only
|
||||
if ((check_error and not calc_is_warnings_only) or
|
||||
@ -279,9 +346,9 @@ class Option(BaseOption):
|
||||
soption_bag.index = _index
|
||||
kwargs['orig_value'] = value
|
||||
|
||||
validator.execute(soption_bag,
|
||||
leadership_must_have_index=True,
|
||||
**kwargs)
|
||||
await validator.execute(soption_bag,
|
||||
leadership_must_have_index=True,
|
||||
**kwargs)
|
||||
except ValueError as err:
|
||||
if calc_is_warnings_only:
|
||||
warnings.warn_explicit(ValueWarning(val,
|
||||
@ -302,8 +369,8 @@ class Option(BaseOption):
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 316)
|
||||
|
||||
def do_validation(_value,
|
||||
_index):
|
||||
async def do_validation(_value,
|
||||
_index):
|
||||
if isinstance(_value, list):
|
||||
raise ValueError(_('which must not be a list').format(_value,
|
||||
self.impl_get_display_name()))
|
||||
@ -313,8 +380,8 @@ class Option(BaseOption):
|
||||
if check_error:
|
||||
# option validation
|
||||
self.validate(_value)
|
||||
self.validate_with_option(_value,
|
||||
option_bag)
|
||||
await self.validate_with_option(_value,
|
||||
option_bag)
|
||||
if ((check_error and not is_warnings_only) or
|
||||
(not check_error and is_warnings_only)):
|
||||
try:
|
||||
@ -331,24 +398,24 @@ class Option(BaseOption):
|
||||
self.__class__.__name__, 0)
|
||||
else:
|
||||
raise err
|
||||
calculation_validator(_value,
|
||||
_index)
|
||||
await calculation_validator(_value,
|
||||
_index)
|
||||
try:
|
||||
val = value
|
||||
err_index = force_index
|
||||
if not self.impl_is_multi():
|
||||
do_validation(val, None)
|
||||
await do_validation(val, None)
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti():
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('which must be a list'))
|
||||
_is_not_unique(value, option_bag)
|
||||
for val in value:
|
||||
do_validation(val,
|
||||
force_index)
|
||||
await do_validation(val,
|
||||
force_index)
|
||||
else:
|
||||
do_validation(val,
|
||||
force_index)
|
||||
await do_validation(val,
|
||||
force_index)
|
||||
elif isinstance(value, Calculation) and config_bag is undefined:
|
||||
pass
|
||||
elif not isinstance(value, list):
|
||||
@ -362,14 +429,14 @@ class Option(BaseOption):
|
||||
raise ValueError(_('which "{}" must be a list of list'
|
||||
'').format(lval))
|
||||
for val in lval:
|
||||
do_validation(val,
|
||||
err_index)
|
||||
await do_validation(val,
|
||||
err_index)
|
||||
else:
|
||||
_is_not_unique(value, option_bag)
|
||||
# FIXME subtimal, not several time is whole=True!
|
||||
for err_index, val in enumerate(value):
|
||||
do_validation(val,
|
||||
err_index)
|
||||
await do_validation(val,
|
||||
err_index)
|
||||
except ValueError as err:
|
||||
if config_bag is undefined or \
|
||||
'demoting_error_warning' not in config_bag.properties:
|
||||
@ -399,9 +466,14 @@ class Option(BaseOption):
|
||||
raise ValueError(_('default value not allowed if option "{0}" '
|
||||
'is calculated').format(self.impl_getname()))
|
||||
|
||||
def validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
def sync_validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
pass
|
||||
|
||||
async def validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
pass
|
||||
|
||||
def second_level_validation(self,
|
||||
|
@ -35,14 +35,14 @@ class CacheOptionDescription(BaseOption):
|
||||
def impl_already_build_caches(self) -> bool:
|
||||
return self.impl_is_readonly()
|
||||
|
||||
def _build_cache(self,
|
||||
path='',
|
||||
_consistencies=None,
|
||||
_consistencies_id=0,
|
||||
currpath: List[str]=None,
|
||||
cache_option=None,
|
||||
force_store_values=None,
|
||||
display_name=None) -> None:
|
||||
async def _build_cache(self,
|
||||
path='',
|
||||
_consistencies=None,
|
||||
_consistencies_id=0,
|
||||
currpath: List[str]=None,
|
||||
cache_option=None,
|
||||
force_store_values=None,
|
||||
display_name=None) -> None:
|
||||
"""validate options and set option has readonly option
|
||||
"""
|
||||
# _consistencies is None only when we start to build cache
|
||||
@ -60,20 +60,20 @@ class CacheOptionDescription(BaseOption):
|
||||
# cache already set
|
||||
raise ConfigError(_('option description seems to be part of an other '
|
||||
'config'))
|
||||
for option in self.get_children(config_bag=undefined,
|
||||
dyn=False):
|
||||
for option in await self.get_children(config_bag=undefined,
|
||||
dyn=False):
|
||||
if __debug__:
|
||||
cache_option.append(option)
|
||||
sub_currpath = currpath + [option.impl_getname()]
|
||||
subpath = '.'.join(sub_currpath)
|
||||
if isinstance(option, OptionDescription):
|
||||
option._build_cache(subpath,
|
||||
_consistencies,
|
||||
_consistencies_id,
|
||||
sub_currpath,
|
||||
cache_option,
|
||||
force_store_values,
|
||||
display_name)
|
||||
await option._build_cache(subpath,
|
||||
_consistencies,
|
||||
_consistencies_id,
|
||||
sub_currpath,
|
||||
cache_option,
|
||||
force_store_values,
|
||||
display_name)
|
||||
else:
|
||||
is_multi = option.impl_is_multi()
|
||||
if not option.impl_is_symlinkoption():
|
||||
@ -94,10 +94,6 @@ class CacheOptionDescription(BaseOption):
|
||||
'"force_metaconfig_on_freeze" '
|
||||
'property without "frozen"'
|
||||
'').format(option.impl_get_display_name()))
|
||||
# if context is set to callback, must be reset each time a value change
|
||||
if hasattr(option, '_has_calc_context'):
|
||||
self._add_dependency(option)
|
||||
|
||||
if option.impl_is_readonly():
|
||||
raise ConflictError(_('duplicate option: {0}').format(option))
|
||||
if not self.impl_is_readonly() and display_name:
|
||||
@ -109,17 +105,14 @@ class CacheOptionDescription(BaseOption):
|
||||
self._path = self._name
|
||||
self._set_readonly()
|
||||
|
||||
def impl_build_force_store_values(self,
|
||||
config_bag: ConfigBag) -> None:
|
||||
if not hasattr(self, '_cache_force_store_values'):
|
||||
raise ConfigError(_('option description seems to be part of an other '
|
||||
'config'))
|
||||
async def impl_build_force_store_values(self,
|
||||
config_bag: ConfigBag) -> None:
|
||||
if 'force_store_value' not in config_bag.properties:
|
||||
return
|
||||
commit = False
|
||||
values = config_bag.context.cfgimpl_get_values()
|
||||
for subpath, option in self._cache_force_store_values:
|
||||
if not values._p_.hasvalue(subpath):
|
||||
if not await values._p_.hasvalue(subpath):
|
||||
if option.impl_is_follower():
|
||||
option_bag = OptionBag()
|
||||
leader = option.impl_get_leadership().get_leader()
|
||||
@ -128,7 +121,7 @@ class CacheOptionDescription(BaseOption):
|
||||
None,
|
||||
config_bag)
|
||||
option_bag.properties = frozenset()
|
||||
follower_len = len(values.getvalue(option_bag))
|
||||
follower_len = len(await values.getvalue(option_bag))
|
||||
for index in range(follower_len):
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
@ -136,11 +129,11 @@ class CacheOptionDescription(BaseOption):
|
||||
index,
|
||||
config_bag)
|
||||
option_bag.properties = frozenset()
|
||||
values._p_.setvalue(subpath,
|
||||
values.getvalue(option_bag),
|
||||
owners.forced,
|
||||
index,
|
||||
False)
|
||||
await values._p_.setvalue(subpath,
|
||||
await values.getvalue(option_bag),
|
||||
owners.forced,
|
||||
index,
|
||||
False)
|
||||
else:
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
@ -148,24 +141,24 @@ class CacheOptionDescription(BaseOption):
|
||||
None,
|
||||
config_bag)
|
||||
option_bag.properties = frozenset()
|
||||
values._p_.setvalue(subpath,
|
||||
values.getvalue(option_bag),
|
||||
owners.forced,
|
||||
None,
|
||||
False)
|
||||
await values._p_.setvalue(subpath,
|
||||
await values.getvalue(option_bag),
|
||||
owners.forced,
|
||||
None,
|
||||
False)
|
||||
commit = True
|
||||
|
||||
if commit:
|
||||
values._p_.commit()
|
||||
await values._p_.commit()
|
||||
|
||||
|
||||
class OptionDescriptionWalk(CacheOptionDescription):
|
||||
__slots__ = ('_children',)
|
||||
|
||||
def get_child(self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
subpath: str) -> Union[BaseOption, SynDynOptionDescription]:
|
||||
async def get_child(self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
subpath: str) -> Union[BaseOption, SynDynOptionDescription]:
|
||||
# if not dyn
|
||||
if name in self._children[0]:
|
||||
return self._children[1][self._children[0].index(name)]
|
||||
@ -174,7 +167,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
if child.impl_is_dynoptiondescription():
|
||||
cname = child.impl_getname()
|
||||
if name.startswith(cname):
|
||||
for suffix in child.get_suffixes(config_bag):
|
||||
for suffix in await child.get_suffixes(config_bag):
|
||||
if name == cname + child.convert_suffix_to_path(suffix):
|
||||
return child.to_dynoption(subpath,
|
||||
suffix,
|
||||
@ -188,35 +181,37 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
'in optiondescription "{1}"'
|
||||
'').format(name, self.impl_get_display_name()))
|
||||
|
||||
def get_children(self,
|
||||
config_bag: Union[ConfigBag, Undefined],
|
||||
dyn: bool=True) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
async def get_children(self,
|
||||
config_bag: Union[ConfigBag, Undefined],
|
||||
dyn: bool=True) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
if not dyn or config_bag is undefined or \
|
||||
config_bag.context.cfgimpl_get_description() == self:
|
||||
subpath = ''
|
||||
else:
|
||||
subpath = self.impl_getpath()
|
||||
children = []
|
||||
for child in self._children[1]:
|
||||
if dyn and child.impl_is_dynoptiondescription():
|
||||
for suffix in child.get_suffixes(config_bag):
|
||||
yield child.to_dynoption(subpath,
|
||||
suffix,
|
||||
child)
|
||||
for suffix in await child.get_suffixes(config_bag):
|
||||
children.append(child.to_dynoption(subpath,
|
||||
suffix,
|
||||
child))
|
||||
else:
|
||||
yield child
|
||||
children.append(child)
|
||||
return children
|
||||
|
||||
def get_children_recursively(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
async def get_children_recursively(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
if self_opt is None:
|
||||
self_opt = self
|
||||
for option in self_opt.get_children(config_bag):
|
||||
for option in await self_opt.get_children(config_bag):
|
||||
if option.impl_is_optiondescription():
|
||||
for subopt in option.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag):
|
||||
async for subopt in option.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag):
|
||||
yield subopt
|
||||
elif (byname is None or option.impl_getname() == byname) and \
|
||||
(bytype is None or isinstance(option, bytype)):
|
||||
|
@ -39,8 +39,6 @@ class SynDynOptionDescription:
|
||||
subpath: str,
|
||||
suffix: str,
|
||||
ori_dyn) -> None:
|
||||
if opt.__class__.__name__.startswith('L') and ori_dyn is None:
|
||||
raise Exception()
|
||||
self._opt = opt
|
||||
if subpath is None:
|
||||
subpath = ''
|
||||
@ -59,10 +57,10 @@ class SynDynOptionDescription:
|
||||
def impl_getopt(self) -> BaseOption:
|
||||
return self._opt
|
||||
|
||||
def get_child(self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
subpath: str) -> BaseOption:
|
||||
async def get_child(self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
subpath: str) -> BaseOption:
|
||||
if name.endswith(self._suffix):
|
||||
oname = name[:-len(self._suffix)]
|
||||
try:
|
||||
@ -78,43 +76,39 @@ class SynDynOptionDescription:
|
||||
'in dynamic optiondescription "{1}"'
|
||||
'').format(name, self.impl_get_display_name()))
|
||||
|
||||
def impl_getname(self,
|
||||
for_path=False) -> str:
|
||||
if for_path == 'toto':
|
||||
if self.ori_dyn:
|
||||
opt = self.ori_dyn
|
||||
else:
|
||||
opt = self._opt
|
||||
return self._opt.impl_getname() + opt.convert_suffix_to_path(self._suffix)
|
||||
def impl_getname(self) -> str:
|
||||
return self._opt.impl_getname() + self._suffix
|
||||
|
||||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
return True
|
||||
|
||||
def get_children(self,
|
||||
config_bag: ConfigBag,
|
||||
dyn: bool=True):
|
||||
async def get_children(self,
|
||||
config_bag: ConfigBag,
|
||||
dyn: bool=True):
|
||||
subpath = self.impl_getpath()
|
||||
for child in self._opt.get_children(config_bag):
|
||||
yield child.to_dynoption(subpath,
|
||||
self._suffix,
|
||||
self._opt)
|
||||
children = []
|
||||
for child in await self._opt.get_children(config_bag):
|
||||
children.append(child.to_dynoption(subpath,
|
||||
self._suffix,
|
||||
self._opt))
|
||||
return children
|
||||
|
||||
def get_children_recursively(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None) -> BaseOption:
|
||||
return self._opt.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag,
|
||||
self)
|
||||
async def get_children_recursively(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None) -> BaseOption:
|
||||
async for option in self._opt.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag,
|
||||
self):
|
||||
yield option
|
||||
|
||||
def impl_getpath(self) -> str:
|
||||
subpath = self._subpath
|
||||
if subpath != '':
|
||||
subpath += '.'
|
||||
return subpath + self.impl_getname(for_path=True)
|
||||
return subpath + self.impl_getname()
|
||||
|
||||
def impl_get_display_name(self) -> str:
|
||||
return self._opt.impl_get_display_name() + self._suffix
|
||||
@ -145,9 +139,9 @@ class SynDynLeadership(SynDynOptionDescription):
|
||||
config_bag,
|
||||
resetted_opts)
|
||||
|
||||
def pop(self,
|
||||
*args,
|
||||
**kwargs) -> None:
|
||||
self._opt.pop(*args,
|
||||
followers=self.get_followers(),
|
||||
**kwargs)
|
||||
async def pop(self,
|
||||
*args,
|
||||
**kwargs) -> None:
|
||||
await self._opt.pop(*args,
|
||||
followers=self.get_followers(),
|
||||
**kwargs)
|
||||
|
@ -18,6 +18,7 @@
|
||||
from itertools import chain
|
||||
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list
|
||||
from .i18n import _
|
||||
from .asyncinit import asyncinit
|
||||
|
||||
|
||||
"""If cache and expire is enable, time before cache is expired.
|
||||
@ -153,18 +154,13 @@ class OptionBag:
|
||||
self.config_bag = config_bag
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key == 'properties':
|
||||
settings = self.config_bag.context.cfgimpl_get_settings()
|
||||
self.properties = settings.getproperties(self,
|
||||
apply_requires=self.apply_requires)
|
||||
return self.properties
|
||||
elif key == 'ori_option':
|
||||
if key == 'ori_option':
|
||||
return self.option
|
||||
elif key == 'apply_requires':
|
||||
return True
|
||||
elif key == 'properties_setted':
|
||||
return False
|
||||
raise KeyError('unknown key {} for OptionBag'.format(key)) # pragma: no cover
|
||||
raise KeyError('unknown key "{}" for OptionBag'.format(key)) # pragma: no cover
|
||||
|
||||
def __setattr__(self, key, val):
|
||||
super().__setattr__(key, val)
|
||||
@ -178,7 +174,7 @@ class OptionBag:
|
||||
except AttributeError:
|
||||
pass
|
||||
return
|
||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||
raise KeyError(_('cannot delete key "{}" for OptionBag').format(key)) # pragma: no cover
|
||||
|
||||
def copy(self):
|
||||
option_bag = OptionBag()
|
||||
@ -199,20 +195,18 @@ class ConfigBag:
|
||||
'expiration_time' # EXPIRATION_TIME
|
||||
)
|
||||
|
||||
def __init__(self, context, **kwargs):
|
||||
def __init__(self,
|
||||
context,
|
||||
properties: set,
|
||||
permissives: frozenset,
|
||||
**kwargs):
|
||||
self.context = context
|
||||
self.properties = properties
|
||||
self.permissives = permissives
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key == 'properties':
|
||||
settings = self.context.cfgimpl_get_settings()
|
||||
self.properties = settings.get_context_properties(self.context._impl_properties_cache)
|
||||
return self.properties
|
||||
if key == 'permissives':
|
||||
settings = self.context.cfgimpl_get_settings()
|
||||
self.permissives = settings.get_context_permissives()
|
||||
return self.permissives
|
||||
if key == 'true_properties':
|
||||
return self.properties
|
||||
if key == 'expiration_time':
|
||||
@ -220,7 +214,10 @@ class ConfigBag:
|
||||
return self.expiration_time
|
||||
if key == 'is_unrestraint':
|
||||
return False
|
||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||
raise KeyError('unknown key "{}" for ConfigBag'.format(key)) # pragma: no cover
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
super().__setattr__(key, value)
|
||||
|
||||
def remove_warnings(self):
|
||||
self.properties = frozenset(self.properties - {'warnings'})
|
||||
@ -236,22 +233,9 @@ class ConfigBag:
|
||||
def set_permissive(self):
|
||||
self.properties = frozenset(self.properties | {'permissive'})
|
||||
|
||||
def __delattr__(self, key):
|
||||
if key in ['properties', 'permissives']:
|
||||
try:
|
||||
super().__delattr__(key)
|
||||
except AttributeError:
|
||||
pass
|
||||
return
|
||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||
|
||||
def copy(self):
|
||||
kwargs = {}
|
||||
for key in self.__slots__:
|
||||
if key in ['properties', 'permissives', 'true_properties'] and \
|
||||
not hasattr(self.context, '_impl_settings'):
|
||||
# not for GroupConfig
|
||||
continue
|
||||
kwargs[key] = getattr(self, key)
|
||||
return ConfigBag(**kwargs)
|
||||
|
||||
@ -406,8 +390,8 @@ class Settings(object):
|
||||
# ____________________________________________________________
|
||||
# get properties and permissive methods
|
||||
|
||||
def get_context_properties(self,
|
||||
cache):
|
||||
async def get_context_properties(self,
|
||||
cache):
|
||||
is_cached, props, validated = cache.getcache(None,
|
||||
None,
|
||||
None,
|
||||
@ -415,9 +399,9 @@ class Settings(object):
|
||||
{},
|
||||
'context_props')
|
||||
if not is_cached:
|
||||
props = self._p_.getproperties(None,
|
||||
None,
|
||||
self.default_properties)
|
||||
props = await self._p_.getproperties(None,
|
||||
None,
|
||||
self.default_properties)
|
||||
cache.setcache(None,
|
||||
None,
|
||||
props,
|
||||
@ -426,10 +410,10 @@ class Settings(object):
|
||||
True)
|
||||
return props
|
||||
|
||||
def getproperties(self,
|
||||
option_bag,
|
||||
apply_requires=True,
|
||||
uncalculated=False):
|
||||
async def getproperties(self,
|
||||
option_bag,
|
||||
apply_requires=True,
|
||||
uncalculated=False):
|
||||
"""
|
||||
"""
|
||||
option = option_bag.option
|
||||
@ -451,20 +435,20 @@ class Settings(object):
|
||||
is_cached = False
|
||||
if not is_cached:
|
||||
props = set()
|
||||
p_props = self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
p_props = await self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
if index is not None:
|
||||
p_props = chain(p_props,
|
||||
self._p_.getproperties(path,
|
||||
index,
|
||||
option.impl_getproperties()))
|
||||
await self._p_.getproperties(path,
|
||||
index,
|
||||
option.impl_getproperties()))
|
||||
for prop in p_props:
|
||||
if uncalculated or isinstance(prop, str):
|
||||
props.add(prop)
|
||||
elif apply_requires:
|
||||
new_prop = prop.execute(option_bag,
|
||||
leadership_must_have_index=True)
|
||||
new_prop = await prop.execute(option_bag,
|
||||
leadership_must_have_index=True)
|
||||
if new_prop is None:
|
||||
continue
|
||||
elif not isinstance(new_prop, str):
|
||||
@ -474,7 +458,7 @@ class Settings(object):
|
||||
if not option.impl_is_optiondescription() and option.impl_is_leader() and new_prop not in ALLOWED_LEADER_PROPERTIES:
|
||||
raise LeadershipError(_('leader cannot have "{}" property').format(new_prop))
|
||||
props.add(new_prop)
|
||||
props -= self.getpermissives(option_bag)
|
||||
props -= await self.getpermissives(option_bag)
|
||||
if not uncalculated and apply_requires and not config_bag.is_unrestraint:
|
||||
cache.setcache(path,
|
||||
index,
|
||||
@ -484,48 +468,48 @@ class Settings(object):
|
||||
True)
|
||||
return props
|
||||
|
||||
def get_calculated_properties(self,
|
||||
option_bag):
|
||||
async def get_calculated_properties(self,
|
||||
option_bag):
|
||||
option = option_bag.option
|
||||
if option.impl_is_symlinkoption():
|
||||
option = option.impl_getopt()
|
||||
path = option.impl_getpath()
|
||||
p_props = self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
p_props = await self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
if option_bag.index is not None:
|
||||
p_props = chain(p_props,
|
||||
self._p_.getproperties(path,
|
||||
option_bag.index,
|
||||
option.impl_getproperties()))
|
||||
await self._p_.getproperties(path,
|
||||
option_bag.index,
|
||||
option.impl_getproperties()))
|
||||
for prop in p_props:
|
||||
if not isinstance(prop, str):
|
||||
yield prop
|
||||
|
||||
def has_properties_index(self,
|
||||
option_bag):
|
||||
async def has_properties_index(self,
|
||||
option_bag):
|
||||
option = option_bag.option
|
||||
if option.impl_is_symlinkoption():
|
||||
option = option.impl_getopt()
|
||||
path = option.impl_getpath()
|
||||
p_props = self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
p_props = await self._p_.getproperties(path,
|
||||
None,
|
||||
option.impl_getproperties())
|
||||
if option_bag.index is not None:
|
||||
p_props = chain(p_props,
|
||||
self._p_.getproperties(path,
|
||||
option_bag.index,
|
||||
option.impl_getproperties()))
|
||||
await self._p_.getproperties(path,
|
||||
option_bag.index,
|
||||
option.impl_getproperties()))
|
||||
for prop in p_props:
|
||||
if not isinstance(prop, str) and prop.has_index(option_bag.option):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_context_permissives(self):
|
||||
return self.getpermissives(None)
|
||||
async def get_context_permissives(self):
|
||||
return await self.getpermissives(None)
|
||||
|
||||
def getpermissives(self,
|
||||
option_bag):
|
||||
async def getpermissives(self,
|
||||
option_bag):
|
||||
if option_bag is None:
|
||||
path = None
|
||||
index = None
|
||||
@ -537,26 +521,27 @@ class Settings(object):
|
||||
else:
|
||||
path = option_bag.path
|
||||
index = option_bag.index
|
||||
permissives = self._pp_.getpermissives(path, None)
|
||||
permissives = await self._pp_.getpermissives(path, None)
|
||||
if index is not None:
|
||||
permissives = frozenset(self._pp_.getpermissives(path, index) | permissives)
|
||||
option_permissives = await self._pp_.getpermissives(path, index)
|
||||
permissives = frozenset(option_permissives | permissives)
|
||||
return permissives
|
||||
|
||||
#____________________________________________________________
|
||||
# set methods
|
||||
def set_context_properties(self,
|
||||
properties,
|
||||
context):
|
||||
self._p_.setproperties(None,
|
||||
None,
|
||||
properties)
|
||||
context.cfgimpl_reset_cache(None)
|
||||
async def set_context_properties(self,
|
||||
properties,
|
||||
context):
|
||||
await self._p_.setproperties(None,
|
||||
None,
|
||||
properties)
|
||||
await context.cfgimpl_reset_cache(None)
|
||||
|
||||
def setproperties(self,
|
||||
path,
|
||||
properties,
|
||||
option_bag,
|
||||
context):
|
||||
async def setproperties(self,
|
||||
path,
|
||||
properties,
|
||||
option_bag,
|
||||
context):
|
||||
"""save properties for specified path
|
||||
(never save properties if same has option properties)
|
||||
"""
|
||||
@ -576,21 +561,21 @@ class Settings(object):
|
||||
raise LeadershipError(_('a leader ({0}) cannot have '
|
||||
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
|
||||
'').format(opt.impl_get_display_name()))
|
||||
self._p_.setproperties(path,
|
||||
option_bag.index,
|
||||
properties)
|
||||
await self._p_.setproperties(path,
|
||||
option_bag.index,
|
||||
properties)
|
||||
# values too because of follower values could have a PropertiesOptionError has value
|
||||
context.cfgimpl_reset_cache(option_bag)
|
||||
del option_bag.properties
|
||||
await context.cfgimpl_reset_cache(option_bag)
|
||||
option_bag.properties = properties
|
||||
|
||||
def set_context_permissives(self,
|
||||
permissives):
|
||||
self.setpermissives(None,
|
||||
permissives)
|
||||
async def set_context_permissives(self,
|
||||
permissives):
|
||||
await self.setpermissives(None,
|
||||
permissives)
|
||||
|
||||
def setpermissives(self,
|
||||
option_bag,
|
||||
permissives):
|
||||
async def setpermissives(self,
|
||||
option_bag,
|
||||
permissives):
|
||||
"""
|
||||
enables us to put the permissives in the storage
|
||||
|
||||
@ -616,16 +601,16 @@ class Settings(object):
|
||||
if forbidden_permissives:
|
||||
raise ConfigError(_('cannot add those permissives: {0}').format(
|
||||
' '.join(forbidden_permissives)))
|
||||
self._pp_.setpermissives(path, index, permissives)
|
||||
await self._pp_.setpermissives(path, index, permissives)
|
||||
if option_bag is not None:
|
||||
option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
await option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
|
||||
#____________________________________________________________
|
||||
# reset methods
|
||||
|
||||
def reset(self,
|
||||
option_bag,
|
||||
context):
|
||||
async def reset(self,
|
||||
option_bag,
|
||||
context):
|
||||
if option_bag is None:
|
||||
opt = None
|
||||
path = None
|
||||
@ -637,12 +622,12 @@ class Settings(object):
|
||||
"").format(opt.impl_get_display_name())
|
||||
path = option_bag.path
|
||||
index = option_bag.index
|
||||
self._p_.delproperties(path, index)
|
||||
context.cfgimpl_reset_cache(option_bag)
|
||||
await self._p_.delproperties(path, index)
|
||||
await context.cfgimpl_reset_cache(option_bag)
|
||||
|
||||
def reset_permissives(self,
|
||||
option_bag,
|
||||
context):
|
||||
async def reset_permissives(self,
|
||||
option_bag,
|
||||
context):
|
||||
if option_bag is None:
|
||||
opt = None
|
||||
path = None
|
||||
@ -654,19 +639,19 @@ class Settings(object):
|
||||
"").format(opt.impl_get_display_name())
|
||||
index = option_bag.index
|
||||
path = option_bag.path
|
||||
self._pp_.delpermissive(path, index)
|
||||
context.cfgimpl_reset_cache(option_bag)
|
||||
await self._pp_.delpermissive(path, index)
|
||||
await context.cfgimpl_reset_cache(option_bag)
|
||||
|
||||
#____________________________________________________________
|
||||
# validate properties
|
||||
def calc_raises_properties(self,
|
||||
option_bag,
|
||||
apply_requires=True):
|
||||
async def calc_raises_properties(self,
|
||||
option_bag,
|
||||
apply_requires=True):
|
||||
if apply_requires and option_bag.properties_setted:
|
||||
option_properties = option_bag.properties
|
||||
else:
|
||||
option_properties = self.getproperties(option_bag,
|
||||
apply_requires=apply_requires)
|
||||
option_properties = await self.getproperties(option_bag,
|
||||
apply_requires=apply_requires)
|
||||
return self._calc_raises_properties(option_bag.config_bag.properties,
|
||||
option_bag.config_bag.permissives,
|
||||
option_properties)
|
||||
@ -683,8 +668,8 @@ class Settings(object):
|
||||
# at this point an option should not remain in properties
|
||||
return properties
|
||||
|
||||
def validate_properties(self,
|
||||
option_bag):
|
||||
async def validate_properties(self,
|
||||
option_bag):
|
||||
"""
|
||||
validation upon the properties related to `opt`
|
||||
|
||||
@ -695,7 +680,7 @@ class Settings(object):
|
||||
config_bag = option_bag.config_bag
|
||||
if not config_bag.properties or config_bag.properties == frozenset(['cache']): # pragma: no cover
|
||||
return
|
||||
properties = self.calc_raises_properties(option_bag)
|
||||
properties = await self.calc_raises_properties(option_bag)
|
||||
if properties != frozenset():
|
||||
raise PropertiesOptionError(option_bag,
|
||||
properties,
|
||||
@ -741,13 +726,13 @@ class Settings(object):
|
||||
#____________________________________________________________
|
||||
# read only/read write
|
||||
|
||||
def _read(self,
|
||||
remove,
|
||||
append,
|
||||
context):
|
||||
props = self._p_.getproperties(None,
|
||||
None,
|
||||
self.default_properties)
|
||||
async def _read(self,
|
||||
remove,
|
||||
append,
|
||||
context):
|
||||
props = await self._p_.getproperties(None,
|
||||
None,
|
||||
self.default_properties)
|
||||
modified = False
|
||||
if remove & props:
|
||||
props = props - remove
|
||||
@ -756,19 +741,19 @@ class Settings(object):
|
||||
props = props | append
|
||||
modified = True
|
||||
if modified:
|
||||
self.set_context_properties(frozenset(props),
|
||||
context)
|
||||
await self.set_context_properties(frozenset(props),
|
||||
context)
|
||||
|
||||
def read_only(self,
|
||||
context):
|
||||
async def read_only(self,
|
||||
context):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(self.ro_remove,
|
||||
self.ro_append,
|
||||
context)
|
||||
await self._read(self.ro_remove,
|
||||
self.ro_append,
|
||||
context)
|
||||
|
||||
def read_write(self,
|
||||
context):
|
||||
async def read_write(self,
|
||||
context):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(self.rw_remove,
|
||||
self.rw_append,
|
||||
context)
|
||||
await self._read(self.rw_remove,
|
||||
self.rw_append,
|
||||
context)
|
||||
|
@ -97,32 +97,34 @@ def gen_storage_id(session_id,
|
||||
return 'c' + str(id(config)) + str(int(time())) + str(randint(0, 500))
|
||||
|
||||
|
||||
def get_storages(context,
|
||||
session_id,
|
||||
persistent,
|
||||
storage):
|
||||
async def get_storages(context,
|
||||
session_id,
|
||||
persistent,
|
||||
storage):
|
||||
session_id = gen_storage_id(session_id,
|
||||
context)
|
||||
if storage is None:
|
||||
storage = default_storage
|
||||
imp = storage.get()
|
||||
imp_storage = imp.Storage(session_id,
|
||||
persistent)
|
||||
imp_storage = await imp.Storage(session_id,
|
||||
persistent)
|
||||
properties = imp.Properties(imp_storage)
|
||||
permissives = imp.Permissives(imp_storage)
|
||||
values = imp.Values(imp_storage)
|
||||
return properties, permissives, values, session_id
|
||||
|
||||
|
||||
def get_default_values_storages():
|
||||
async def get_default_values_storages():
|
||||
imp = memory_storage.get()
|
||||
storage = imp.Storage('__validator_storage', persistent=False, test=True)
|
||||
storage = await imp.Storage('__validator_storage',
|
||||
persistent=False,
|
||||
test=True)
|
||||
return imp.Values(storage)
|
||||
|
||||
|
||||
def get_default_settings_storages():
|
||||
async def get_default_settings_storages():
|
||||
imp = memory_storage.get()
|
||||
storage = imp.Storage('__validator_storage', persistent=False, test=True)
|
||||
storage = await imp.Storage('__validator_storage', persistent=False, test=True)
|
||||
properties = imp.Properties(storage)
|
||||
permissives = imp.Permissives(storage)
|
||||
return properties, permissives
|
||||
|
@ -30,11 +30,11 @@ class Properties:
|
||||
self._storage = storage
|
||||
|
||||
# properties
|
||||
def setproperties(self, path, index, properties):
|
||||
async def setproperties(self, path, index, properties):
|
||||
log.debug('setproperties %s %s %s', path, index, properties)
|
||||
self._properties.setdefault(path, {})[index] = properties
|
||||
|
||||
def getproperties(self, path, index, default_properties):
|
||||
async def getproperties(self, path, index, default_properties):
|
||||
if path not in self._properties:
|
||||
ret = frozenset(default_properties)
|
||||
else:
|
||||
@ -42,19 +42,19 @@ class Properties:
|
||||
log.debug('getproperties %s %s %s', path, index, ret)
|
||||
return ret
|
||||
|
||||
def delproperties(self, path, index):
|
||||
async def delproperties(self, path, index):
|
||||
log.debug('delproperties %s', path)
|
||||
if path in self._properties and index in self._properties[path]:
|
||||
del(self._properties[path][index])
|
||||
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""return all modified settings in a dictionary
|
||||
example: {'path1': set(['prop1', 'prop2'])}
|
||||
"""
|
||||
return deepcopy(self._properties)
|
||||
|
||||
def importation(self, properties):
|
||||
async def importation(self, properties):
|
||||
self._properties = properties
|
||||
|
||||
|
||||
@ -67,11 +67,11 @@ class Permissives:
|
||||
self._permissives = {}
|
||||
self._storage = storage
|
||||
|
||||
def setpermissives(self, path, index, permissives):
|
||||
async def setpermissives(self, path, index, permissives):
|
||||
log.debug('setpermissives %s %s', path, permissives)
|
||||
self._permissives.setdefault(path, {})[index] = permissives
|
||||
|
||||
def getpermissives(self, path, index):
|
||||
async def getpermissives(self, path, index):
|
||||
if not path in self._permissives:
|
||||
ret = frozenset()
|
||||
else:
|
||||
@ -79,16 +79,16 @@ class Permissives:
|
||||
log.debug('getpermissives %s %s', path, ret)
|
||||
return ret
|
||||
|
||||
def delpermissive(self, path, index):
|
||||
async def delpermissive(self, path, index):
|
||||
log.debug('delpermissive %s', path)
|
||||
if path in self._permissives and index in self._permissives[path]:
|
||||
del(self._permissives[path][index])
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""return all modified permissives in a dictionary
|
||||
example: {'path1': set(['perm1', 'perm2'])}
|
||||
"""
|
||||
return deepcopy(self._permissives)
|
||||
|
||||
def importation(self, permissives):
|
||||
async def importation(self, permissives):
|
||||
self._permissives = permissives
|
||||
|
@ -16,6 +16,7 @@
|
||||
# ____________________________________________________________
|
||||
from ...i18n import _
|
||||
from ...error import ConflictError
|
||||
from ...asyncinit import asyncinit
|
||||
|
||||
|
||||
class Setting:
|
||||
@ -33,13 +34,14 @@ def list_sessions():
|
||||
return _list_sessions
|
||||
|
||||
|
||||
@asyncinit
|
||||
class Storage:
|
||||
__slots__ = ('session_id', 'persistent')
|
||||
storage = 'dictionary'
|
||||
# if object could be serializable
|
||||
serializable = True
|
||||
|
||||
def __init__(self, session_id, persistent, test=False):
|
||||
async def __init__(self, session_id, persistent, test=False):
|
||||
if not test and session_id in _list_sessions:
|
||||
raise ConflictError(_('session "{}" already exists').format(session_id))
|
||||
if persistent:
|
||||
|
@ -35,7 +35,7 @@ class Values:
|
||||
self._informations = {}
|
||||
self._storage = storage
|
||||
|
||||
def commit(self):
|
||||
async def commit(self):
|
||||
pass
|
||||
|
||||
def _setvalue_info(self, nb, idx, value, index, follower_idx=None):
|
||||
@ -72,12 +72,12 @@ class Values:
|
||||
self._values[nb].append([value])
|
||||
|
||||
# value
|
||||
def setvalue(self,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit):
|
||||
async def setvalue(self,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit):
|
||||
"""set value for a path
|
||||
a specified value must be associated to an owner
|
||||
"""
|
||||
@ -97,7 +97,7 @@ class Values:
|
||||
self._add_new_value(index, 2, value)
|
||||
self._add_new_value(index, 3, owner)
|
||||
|
||||
def hasvalue(self, path, index=None):
|
||||
async def hasvalue(self, path, index=None):
|
||||
"""if path has a value
|
||||
return: boolean
|
||||
"""
|
||||
@ -111,7 +111,7 @@ class Values:
|
||||
return index in indexes
|
||||
return False
|
||||
|
||||
def reduce_index(self, path, index):
|
||||
async def reduce_index(self, path, index):
|
||||
"""
|
||||
_values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2))
|
||||
"""
|
||||
@ -122,10 +122,10 @@ class Values:
|
||||
# reduce to one the index
|
||||
self._values[1][path_idx][subidx] -= 1
|
||||
|
||||
def resetvalue_index(self,
|
||||
path,
|
||||
index,
|
||||
commit):
|
||||
async def resetvalue_index(self,
|
||||
path,
|
||||
index,
|
||||
commit):
|
||||
log.debug('resetvalue_index %s %s %s', path, index, id(self))
|
||||
def _resetvalue(nb):
|
||||
del self._values[nb][path_idx]
|
||||
@ -147,9 +147,9 @@ class Values:
|
||||
_resetvalue_index(2)
|
||||
_resetvalue_index(3)
|
||||
|
||||
def resetvalue(self,
|
||||
path,
|
||||
commit):
|
||||
async def resetvalue(self,
|
||||
path,
|
||||
commit):
|
||||
"""remove value means delete value in storage
|
||||
"""
|
||||
log.debug('resetvalue %s %s', path, id(self))
|
||||
@ -163,10 +163,10 @@ class Values:
|
||||
_resetvalue(3)
|
||||
|
||||
# owner
|
||||
def setowner(self,
|
||||
path,
|
||||
owner,
|
||||
index=None):
|
||||
async def setowner(self,
|
||||
path,
|
||||
owner,
|
||||
index=None):
|
||||
"""change owner for a path
|
||||
"""
|
||||
idx = self._values[0].index(path)
|
||||
@ -176,19 +176,11 @@ class Values:
|
||||
follower_idx = self._values[1][idx].index(index)
|
||||
self._setvalue_info(3, idx, owner, index, follower_idx)
|
||||
|
||||
def get_max_length(self,
|
||||
path):
|
||||
if path in self._values[0]:
|
||||
idx = self._values[0].index(path)
|
||||
else:
|
||||
return 0
|
||||
return max(self._values[1][idx]) + 1
|
||||
|
||||
def getowner(self,
|
||||
path,
|
||||
default,
|
||||
index=None,
|
||||
with_value=False):
|
||||
async def getowner(self,
|
||||
path,
|
||||
default,
|
||||
index=None,
|
||||
with_value=False):
|
||||
"""get owner for a path
|
||||
return: owner object
|
||||
"""
|
||||
@ -236,7 +228,7 @@ class Values:
|
||||
value = list(value)
|
||||
return owner, value
|
||||
|
||||
def set_information(self, path, key, value):
|
||||
async def set_information(self, path, key, value):
|
||||
"""updates the information's attribute
|
||||
(which is a dictionary)
|
||||
|
||||
@ -246,7 +238,7 @@ class Values:
|
||||
self._informations.setdefault(path, {})
|
||||
self._informations[path][key] = value
|
||||
|
||||
def get_information(self, path, key, default):
|
||||
async def get_information(self, path, key, default):
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
@ -257,28 +249,36 @@ class Values:
|
||||
" not found: {0}").format(key))
|
||||
return value
|
||||
|
||||
def del_information(self, path, key, raises):
|
||||
async def del_information(self, path, key, raises):
|
||||
if path in self._informations and key in self._informations[path]:
|
||||
del self._informations[path][key]
|
||||
else:
|
||||
if raises:
|
||||
raise ValueError(_("information's item not found {0}").format(key))
|
||||
|
||||
def list_information(self, path):
|
||||
async def list_information(self, path):
|
||||
if path in self._informations:
|
||||
return self._informations[path].keys()
|
||||
else:
|
||||
return []
|
||||
|
||||
def del_informations(self):
|
||||
async def del_informations(self):
|
||||
self._informations = {}
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
return deepcopy(self._values)
|
||||
|
||||
def importation(self, export):
|
||||
async def importation(self, export):
|
||||
self._values = deepcopy(export)
|
||||
|
||||
async def get_max_length(self,
|
||||
path):
|
||||
if path in self._values[0]:
|
||||
idx = self._values[0].index(path)
|
||||
else:
|
||||
return 0
|
||||
return max(self._values[1][idx]) + 1
|
||||
|
||||
|
||||
def delete_session(session_id):
|
||||
raise ValueError(_('cannot delete none persistent session'))
|
||||
|
@ -26,18 +26,15 @@ class Properties(Sqlite3DB):
|
||||
super(Properties, self).__init__(storage)
|
||||
|
||||
# properties
|
||||
def setproperties(self, path, index, properties):
|
||||
self.exportation()
|
||||
self.delproperties(path, index, commit=False)
|
||||
self.exportation()
|
||||
self._storage.execute("INSERT INTO property(path, tiram_index, properties, session_id) VALUES "
|
||||
"(?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(properties),
|
||||
self._session_id))
|
||||
self.exportation()
|
||||
async def setproperties(self, path, index, properties):
|
||||
await self.delproperties(path, index, commit=False)
|
||||
await self._storage.execute("INSERT INTO property(path, tiram_index, properties, session_id) VALUES "
|
||||
"(?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(properties),
|
||||
self._session_id))
|
||||
|
||||
def getproperties(self, path, index, default_properties):
|
||||
async def getproperties(self, path, index, default_properties):
|
||||
sql = 'SELECT properties FROM property WHERE session_id = ? '
|
||||
params = [self._session_id]
|
||||
if path is None:
|
||||
@ -50,13 +47,13 @@ class Properties(Sqlite3DB):
|
||||
else:
|
||||
sql += "AND tiram_index = ? LIMIT 1"
|
||||
params.append(index)
|
||||
value = self._storage.select(sql, params)
|
||||
value = await self._storage.select(sql, params)
|
||||
if value is None:
|
||||
return set(default_properties)
|
||||
else:
|
||||
return set(self._sqlite_decode(value[0]))
|
||||
|
||||
def delproperties(self, path, index, commit=True):
|
||||
async def delproperties(self, path, index, commit=True):
|
||||
sql = 'DELETE FROM property WHERE session_id = ? '
|
||||
params = [self._session_id]
|
||||
if path is None:
|
||||
@ -69,25 +66,25 @@ class Properties(Sqlite3DB):
|
||||
else:
|
||||
params.append(index)
|
||||
sql += 'AND tiram_index = ?'
|
||||
self._storage.execute(sql, params, commit)
|
||||
await self._storage.execute(sql, params, commit)
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""return all modified settings in a dictionary
|
||||
example: {'path1': set(['prop1', 'prop2'])}
|
||||
"""
|
||||
ret = {}
|
||||
for path, tiram_index, properties, _ in self._storage.select("SELECT * FROM property "
|
||||
for path, tiram_index, properties, _ in await self._storage.select("SELECT * FROM property "
|
||||
"WHERE session_id = ?",
|
||||
(self._session_id,),
|
||||
only_one=False):
|
||||
ret.setdefault(path, {})[tiram_index] = self._sqlite_decode(properties)
|
||||
return ret
|
||||
|
||||
def importation(self, properties):
|
||||
self._storage.execute("DELETE FROM property WHERE session_id = ?", (self._session_id,), commit=False)
|
||||
async def importation(self, properties):
|
||||
await self._storage.execute("DELETE FROM property WHERE session_id = ?", (self._session_id,), commit=False)
|
||||
for path, indexed_properties in properties.items():
|
||||
for index, property_ in indexed_properties.items():
|
||||
self._storage.execute("INSERT INTO property(path, tiram_index, properties, session_id) "
|
||||
await self._storage.execute("INSERT INTO property(path, tiram_index, properties, session_id) "
|
||||
"VALUES (?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(property_),
|
||||
@ -100,16 +97,16 @@ class Permissives(Sqlite3DB):
|
||||
__slots__ = tuple()
|
||||
|
||||
# permissive
|
||||
def setpermissives(self, path, index, permissive):
|
||||
async def setpermissives(self, path, index, permissive):
|
||||
log.debug('setpermissive %s %s %s %s', path, index, permissive, id(self))
|
||||
self.delpermissive(path, index, commit=False)
|
||||
self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
|
||||
await self.delpermissive(path, index, commit=False)
|
||||
await self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
|
||||
"VALUES (?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(permissive),
|
||||
self._session_id))
|
||||
|
||||
def getpermissives(self, path, index):
|
||||
async def getpermissives(self, path, index):
|
||||
sql = 'SELECT permissives FROM permissive WHERE session_id = ? '
|
||||
params = [self._session_id]
|
||||
if path is None:
|
||||
@ -122,7 +119,7 @@ class Permissives(Sqlite3DB):
|
||||
else:
|
||||
sql += "AND tiram_index = ? LIMIT 1"
|
||||
params.append(index)
|
||||
permissives = self._storage.select(sql, params)
|
||||
permissives = await self._storage.select(sql, params)
|
||||
if permissives is None:
|
||||
ret = frozenset()
|
||||
else:
|
||||
@ -130,7 +127,7 @@ class Permissives(Sqlite3DB):
|
||||
log.debug('getpermissive %s %s %s', path, ret, id(self))
|
||||
return ret
|
||||
|
||||
def delpermissive(self, path, index, commit=True):
|
||||
async def delpermissive(self, path, index, commit=True):
|
||||
sql = 'DELETE FROM permissive WHERE session_id = ? '
|
||||
params = [self._session_id]
|
||||
if path is None:
|
||||
@ -143,29 +140,29 @@ class Permissives(Sqlite3DB):
|
||||
else:
|
||||
params.append(index)
|
||||
sql += 'AND tiram_index = ?'
|
||||
self._storage.execute(sql, params, commit)
|
||||
await self._storage.execute(sql, params, commit)
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
"""return all modified permissives in a dictionary
|
||||
example: {'path1': set(['perm1', 'perm2'])}
|
||||
"""
|
||||
ret = {}
|
||||
for path, index, permissives in self._storage.select("SELECT path, tiram_index, permissives FROM permissive "
|
||||
"WHERE session_id = ?",
|
||||
(self._session_id,),
|
||||
only_one=False):
|
||||
sql = "SELECT path, tiram_index, permissives FROM permissive WHERE session_id = ?"
|
||||
for path, index, permissives in await self._storage.select(sql,
|
||||
(self._session_id,),
|
||||
only_one=False):
|
||||
ret.setdefault(path, {})[index] = self._sqlite_decode(permissives)
|
||||
return ret
|
||||
|
||||
def importation(self, permissives):
|
||||
self._storage.execute("DELETE FROM permissive WHERE session_id = ?", (self._session_id,),
|
||||
commit=False)
|
||||
async def importation(self, permissives):
|
||||
await self._storage.execute("DELETE FROM permissive WHERE session_id = ?", (self._session_id,),
|
||||
commit=False)
|
||||
for path, indexed_permissives in permissives.items():
|
||||
for index, permissive in indexed_permissives.items():
|
||||
self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
|
||||
"VALUES (?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(permissive),
|
||||
self._session_id,
|
||||
), False)
|
||||
await self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
|
||||
"VALUES (?, ?, ?, ?)", (path,
|
||||
index,
|
||||
self._sqlite_encode(permissive),
|
||||
self._session_id,
|
||||
), False)
|
||||
self._storage._conn.commit()
|
||||
|
@ -17,10 +17,12 @@
|
||||
# ____________________________________________________________
|
||||
import sqlite3
|
||||
import warnings
|
||||
from os.path import join
|
||||
from typing import Optional, Dict
|
||||
|
||||
from ...i18n import _
|
||||
from os.path import join
|
||||
from ...error import ConflictError
|
||||
from ...asyncinit import asyncinit
|
||||
|
||||
|
||||
global CONN
|
||||
@ -86,11 +88,19 @@ def delete_session(session_id,
|
||||
cursor.close()
|
||||
|
||||
|
||||
@asyncinit
|
||||
class Storage:
|
||||
__slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'session_name', 'created')
|
||||
__slots__ = ('_conn',
|
||||
'_cursor',
|
||||
'persistent',
|
||||
'session_id',
|
||||
'session_name',
|
||||
'created')
|
||||
storage = 'sqlite3'
|
||||
|
||||
def __init__(self, session_id, persistent, test=False):
|
||||
async def __init__(self,
|
||||
session_id: str,
|
||||
persistent: bool):
|
||||
self.created = False
|
||||
self.persistent = persistent
|
||||
global CONN
|
||||
@ -119,44 +129,56 @@ class Storage:
|
||||
informations_table += 'value TEXT, session_id INTEGER, path TEXT, '
|
||||
informations_table += 'PRIMARY KEY (key, session_id), '
|
||||
informations_table += 'FOREIGN KEY(session_id) REFERENCES session(session_id))'
|
||||
self.execute(session_table, commit=False)
|
||||
self.execute(values_table, commit=False)
|
||||
self.execute(informations_table, commit=False)
|
||||
self.execute(settings_table, commit=False)
|
||||
self.execute(permissives_table, commit=False)
|
||||
self._cursor.execute(session_table)
|
||||
self._cursor.execute(values_table)
|
||||
self._cursor.execute(informations_table)
|
||||
self._cursor.execute(settings_table)
|
||||
self._cursor.execute(permissives_table)
|
||||
commit_needed = True
|
||||
else:
|
||||
commit_needed = False
|
||||
self.session_id = None
|
||||
if self.persistent:
|
||||
select = self.select("SELECT session_id FROM session WHERE session = ?", (session_id,))
|
||||
select = await self.select("SELECT session_id FROM session WHERE session = ?", (session_id,))
|
||||
if select is not None:
|
||||
self.session_id = select[0]
|
||||
if self.session_id is None:
|
||||
try:
|
||||
self.execute('INSERT INTO session(session, persistent) VALUES (?, ?)',
|
||||
(session_id, persistent))
|
||||
self._cursor.execute('INSERT INTO session(session, persistent) VALUES (?, ?)',
|
||||
(session_id, persistent))
|
||||
except sqlite3.IntegrityError: # pragma: no cover
|
||||
raise ConflictError(_('session "{}" already exists').format(session_id))
|
||||
commit_needed = True
|
||||
self.session_id = self._cursor.lastrowid
|
||||
if commit_needed:
|
||||
self._conn.commit()
|
||||
self.created = True
|
||||
|
||||
def commit(self):
|
||||
async def commit(self) -> None:
|
||||
self._conn.commit()
|
||||
|
||||
def execute(self, sql, params=None, commit=True):
|
||||
async def execute(self,
|
||||
sql: str,
|
||||
params: Optional[Dict]=None,
|
||||
commit: bool=True) -> None:
|
||||
#print(sql, params, commit)
|
||||
if params is None:
|
||||
params = tuple()
|
||||
self._cursor.execute(sql, params)
|
||||
if commit:
|
||||
self.commit()
|
||||
await self.commit()
|
||||
|
||||
def select(self, sql, params=None, only_one=True):
|
||||
self.execute(sql, params=params, commit=False)
|
||||
async def select(self,
|
||||
sql: str,
|
||||
params: Optional[Dict]=None,
|
||||
only_one: bool=True) -> 'Row':
|
||||
await self.execute(sql, params=params, commit=False)
|
||||
if only_one:
|
||||
return self._cursor.fetchone()
|
||||
else:
|
||||
return self._cursor.fetchall()
|
||||
|
||||
def __del__(self):
|
||||
def __del__(self) -> None:
|
||||
self._cursor.close()
|
||||
if self.created and not self.persistent:
|
||||
if delete_session is not None:
|
||||
|
@ -32,110 +32,110 @@ class Values(Sqlite3DB):
|
||||
super(Values, self).__init__(storage)
|
||||
|
||||
# sqlite
|
||||
def _sqlite_select(self, path, index):
|
||||
async def _sqlite_select(self, path, index):
|
||||
request = "SELECT value FROM value WHERE path = ? AND session_id = ? "
|
||||
params = (path, self._session_id)
|
||||
if index is not None:
|
||||
request += "and idx = ? "
|
||||
params = (path, self._session_id, index)
|
||||
request += "LIMIT 1"
|
||||
return self._storage.select(request, params)
|
||||
return await self._storage.select(request, params)
|
||||
|
||||
def commit(self):
|
||||
self._storage.commit()
|
||||
async def commit(self):
|
||||
await self._storage.commit()
|
||||
|
||||
# value
|
||||
def setvalue(self,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit):
|
||||
async def setvalue(self,
|
||||
path,
|
||||
value,
|
||||
owner,
|
||||
index,
|
||||
commit):
|
||||
"""set value for an option
|
||||
a specified value must be associated to an owner
|
||||
"""
|
||||
log.debug('setvalue %s %s %s %s %s', path, value, owner, index, commit)
|
||||
path = self._sqlite_encode_path(path)
|
||||
if index is not None:
|
||||
self.resetvalue_index(path,
|
||||
index,
|
||||
commit=False)
|
||||
self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
|
||||
"(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner),
|
||||
index,
|
||||
self._session_id),
|
||||
await self.resetvalue_index(path,
|
||||
index,
|
||||
commit=False)
|
||||
await self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
|
||||
"(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner),
|
||||
index,
|
||||
self._session_id),
|
||||
commit=commit)
|
||||
else:
|
||||
self.resetvalue(path,
|
||||
commit=False)
|
||||
self._storage.execute("INSERT INTO value(path, value, owner, session_id) VALUES "
|
||||
"(?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner),
|
||||
self._session_id),
|
||||
commit=commit)
|
||||
await self.resetvalue(path,
|
||||
commit=False)
|
||||
await self._storage.execute("INSERT INTO value(path, value, owner, session_id) VALUES "
|
||||
"(?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner),
|
||||
self._session_id),
|
||||
commit=commit)
|
||||
|
||||
def hasvalue(self,
|
||||
path,
|
||||
index=None):
|
||||
async def hasvalue(self,
|
||||
path,
|
||||
index=None):
|
||||
"""if opt has a value
|
||||
return: boolean
|
||||
"""
|
||||
log.debug('hasvalue %s %s', path, index)
|
||||
path = self._sqlite_encode_path(path)
|
||||
return self._sqlite_select(path, index) is not None
|
||||
return await self._sqlite_select(path, index) is not None
|
||||
|
||||
|
||||
def reduce_index(self, path, index):
|
||||
async def reduce_index(self, path, index):
|
||||
"""
|
||||
_values == ((path1, path2), ((idx1_1, idx1_2), None),
|
||||
((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2))
|
||||
"""
|
||||
log.debug('reduce_index %s %s %s', path, index, id(self))
|
||||
self._storage.execute("UPDATE value SET idx = ? WHERE path = ? and idx = ? "
|
||||
"AND session_id = ?",
|
||||
(index - 1, path, index, self._session_id))
|
||||
await self._storage.execute("UPDATE value SET idx = ? WHERE path = ? and idx = ? "
|
||||
"AND session_id = ?",
|
||||
(index - 1, path, index, self._session_id))
|
||||
|
||||
def resetvalue_index(self,
|
||||
path,
|
||||
index,
|
||||
commit=True):
|
||||
async def resetvalue_index(self,
|
||||
path,
|
||||
index,
|
||||
commit=True):
|
||||
"""remove value means delete value in storage
|
||||
"""
|
||||
log.debug('resetvalue_index %s %s %s', path, index, commit)
|
||||
path = self._sqlite_encode_path(path)
|
||||
self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ? AND idx = ?",
|
||||
(path, self._session_id, index),
|
||||
commit=commit)
|
||||
await self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ? AND idx = ?",
|
||||
(path, self._session_id, index),
|
||||
commit=commit)
|
||||
|
||||
def resetvalue(self,
|
||||
path,
|
||||
commit):
|
||||
async def resetvalue(self,
|
||||
path,
|
||||
commit):
|
||||
"""remove value means delete value in storage
|
||||
"""
|
||||
log.debug('resetvalue %s %s', path, commit)
|
||||
path = self._sqlite_encode_path(path)
|
||||
self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?",
|
||||
(path, self._session_id),
|
||||
commit=commit)
|
||||
await self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?",
|
||||
(path, self._session_id),
|
||||
commit=commit)
|
||||
|
||||
# owner
|
||||
def setowner(self,
|
||||
path,
|
||||
owner,
|
||||
index=None):
|
||||
async def setowner(self,
|
||||
path,
|
||||
owner,
|
||||
index=None):
|
||||
"""change owner for an option
|
||||
"""
|
||||
log.debug('setowner %s %s %s', path, owner, index)
|
||||
path = self._sqlite_encode_path(path)
|
||||
if index is None:
|
||||
self._storage.execute("UPDATE value SET owner = ? WHERE path = ? AND session_id = ?",
|
||||
(str(owner), path, self._session_id))
|
||||
await self._storage.execute("UPDATE value SET owner = ? WHERE path = ? AND session_id = ?",
|
||||
(str(owner), path, self._session_id))
|
||||
else:
|
||||
self._storage.execute("UPDATE value SET owner = ? WHERE path = ? and idx = ? AND session_id = ?",
|
||||
(str(owner), path, index, self._session_id))
|
||||
await self._storage.execute("UPDATE value SET owner = ? WHERE path = ? and idx = ? AND session_id = ?",
|
||||
(str(owner), path, index, self._session_id))
|
||||
|
||||
def getowner(self,
|
||||
async def getowner(self,
|
||||
path,
|
||||
default,
|
||||
index=None,
|
||||
@ -152,7 +152,7 @@ class Values(Sqlite3DB):
|
||||
else:
|
||||
params = (path, self._session_id)
|
||||
request += ' LIMIT 1'
|
||||
owner = self._storage.select(request, params)
|
||||
owner = await self._storage.select(request, params)
|
||||
if owner is None:
|
||||
if not with_value:
|
||||
return default
|
||||
@ -171,7 +171,7 @@ class Values(Sqlite3DB):
|
||||
value = self._sqlite_decode(owner[1])
|
||||
return nowner, value
|
||||
|
||||
def set_information(self, path, key, value):
|
||||
async def set_information(self, path, key, value):
|
||||
"""updates the information's attribute
|
||||
(which is a dictionary)
|
||||
|
||||
@ -180,20 +180,20 @@ class Values(Sqlite3DB):
|
||||
"""
|
||||
log.debug('set_information %s %s', key, value)
|
||||
path = self._sqlite_encode_path(path)
|
||||
self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path),
|
||||
False)
|
||||
self._storage.execute("INSERT INTO information(key, value, session_id, path) VALUES "
|
||||
"(?, ?, ?, ?)", (key, self._sqlite_encode(value), self._session_id, path))
|
||||
await self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path),
|
||||
False)
|
||||
await self._storage.execute("INSERT INTO information(key, value, session_id, path) VALUES "
|
||||
"(?, ?, ?, ?)", (key, self._sqlite_encode(value), self._session_id, path))
|
||||
|
||||
def get_information(self, path, key, default):
|
||||
async def get_information(self, path, key, default):
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
"""
|
||||
log.debug('get_information %s %s', key, default)
|
||||
path = self._sqlite_encode_path(path)
|
||||
value = self._storage.select("SELECT value FROM information WHERE key = ? AND "
|
||||
value = await self._storage.select("SELECT value FROM information WHERE key = ? AND "
|
||||
"session_id = ? AND path = ?",
|
||||
(key, self._session_id, path))
|
||||
if value is None:
|
||||
@ -204,32 +204,35 @@ class Values(Sqlite3DB):
|
||||
else:
|
||||
return self._sqlite_decode(value[0])
|
||||
|
||||
def del_information(self, path, key, raises):
|
||||
async def del_information(self, path, key, raises):
|
||||
log.debug('del_information %s %s', key, raises)
|
||||
path = self._sqlite_encode_path(path)
|
||||
if raises and self._storage.select("SELECT value FROM information WHERE key = ? "
|
||||
"AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path)) is None:
|
||||
information = await self._storage.select("SELECT value FROM information WHERE key = ? "
|
||||
"AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path))
|
||||
if raises and information is None:
|
||||
raise ValueError(_("information's item not found {0}").format(key))
|
||||
self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path))
|
||||
await self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ? AND path = ?",
|
||||
(key, self._session_id, path))
|
||||
|
||||
def list_information(self, path):
|
||||
async def list_information(self, path):
|
||||
path = self._sqlite_encode_path(path)
|
||||
rows = self._storage.select("SELECT key FROM information WHERE session_id = ? AND path = ?",
|
||||
(self._session_id, path),
|
||||
only_one=False)
|
||||
rows = await self._storage.select("SELECT key FROM information WHERE session_id = ? AND path = ?",
|
||||
(self._session_id, path),
|
||||
only_one=False)
|
||||
ret = []
|
||||
for row in rows:
|
||||
yield self._sqlite_decode_path(row[0])
|
||||
ret.append(self._sqlite_decode_path(row[0]))
|
||||
return ret
|
||||
|
||||
def del_informations(self):
|
||||
self._storage.execute("DELETE FROM information WHERE session_id = ?",
|
||||
(self._session_id,))
|
||||
async def del_informations(self):
|
||||
await self._storage.execute("DELETE FROM information WHERE session_id = ?",
|
||||
(self._session_id,))
|
||||
|
||||
def exportation(self):
|
||||
async def exportation(self):
|
||||
log.debug('exportation')
|
||||
rows = self._storage.select("SELECT path, value, owner, idx FROM value WHERE "
|
||||
"session_id = ?;", (self._session_id,), only_one=False)
|
||||
rows = await self._storage.select("SELECT path, value, owner, idx FROM value WHERE "
|
||||
"session_id = ?;", (self._session_id,), only_one=False)
|
||||
ret = [[], [], [], []]
|
||||
for row in rows:
|
||||
path = self._sqlite_decode_path(row[0])
|
||||
@ -255,36 +258,36 @@ class Values(Sqlite3DB):
|
||||
|
||||
return ret
|
||||
|
||||
def importation(self, export):
|
||||
async def importation(self, export):
|
||||
log.debug('importation')
|
||||
request = "DELETE FROM value WHERE session_id = ?"
|
||||
self._storage.execute(request, (self._session_id,),
|
||||
commit=False)
|
||||
await self._storage.execute(request, (self._session_id,),
|
||||
commit=False)
|
||||
for idx, path in enumerate(export[0]):
|
||||
path = self._sqlite_encode_path(path)
|
||||
index = export[1][idx]
|
||||
value = export[2][idx]
|
||||
owner = export[3][idx]
|
||||
if index is None:
|
||||
self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
|
||||
"(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner), index,
|
||||
self._session_id), commit=False)
|
||||
await self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
|
||||
"(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner), index,
|
||||
self._session_id), commit=False)
|
||||
else:
|
||||
for val in zip(index, value, owner):
|
||||
self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id)"
|
||||
"VALUES (?, ?, ?, ?, ?)", (path,
|
||||
self._sqlite_encode(val[1]),
|
||||
str(val[2]), val[0],
|
||||
self._session_id),
|
||||
commit=False)
|
||||
await self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id)"
|
||||
"VALUES (?, ?, ?, ?, ?)", (path,
|
||||
self._sqlite_encode(val[1]),
|
||||
str(val[2]), val[0],
|
||||
self._session_id),
|
||||
commit=False)
|
||||
self._storage._conn.commit()
|
||||
|
||||
def get_max_length(self,
|
||||
path):
|
||||
async def get_max_length(self,
|
||||
path):
|
||||
log.debug('get_max_length %s', path)
|
||||
val_max = self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?",
|
||||
(path, self._session_id), False)
|
||||
val_max = await self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?",
|
||||
(path, self._session_id), False)
|
||||
if val_max[0][0] is None:
|
||||
return 0
|
||||
return val_max[0][0] + 1
|
||||
|
@ -6,7 +6,7 @@ from copy import copy
|
||||
from itertools import chain
|
||||
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError, ConfigError
|
||||
from .setting import undefined
|
||||
from . import SynDynOption, RegexpOption, ChoiceOption, ParamContext, ParamOption
|
||||
from . import SynDynOption, RegexpOption, ChoiceOption, ParamOption
|
||||
from .i18n import _
|
||||
|
||||
|
||||
@ -43,38 +43,36 @@ class Callbacks(object):
|
||||
self.remotable = tiramisu_web.remotable
|
||||
self.callbacks = []
|
||||
|
||||
def add(self,
|
||||
path,
|
||||
childapi,
|
||||
schema,
|
||||
force_store_value):
|
||||
if self.remotable == 'all' or childapi.option.isoptiondescription():
|
||||
async def add(self,
|
||||
path,
|
||||
childapi,
|
||||
schema,
|
||||
force_store_value):
|
||||
if self.remotable == 'all' or await childapi.option.isoptiondescription():
|
||||
return
|
||||
callback, callback_params = childapi.option.callbacks()
|
||||
callback, callback_params = await childapi.option.callbacks()
|
||||
if callback is None: # FIXME ? and force_store_value and self.clearable != 'all':
|
||||
return
|
||||
self.callbacks.append((callback, callback_params, path, childapi, schema, force_store_value))
|
||||
|
||||
def process_properties(self, form):
|
||||
async def process_properties(self, form):
|
||||
for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
|
||||
if childapi.option.isfollower():
|
||||
self.tiramisu_web.set_remotable(path, form, childapi)
|
||||
if await childapi.option.isfollower():
|
||||
await self.tiramisu_web.set_remotable(path, form, childapi)
|
||||
continue
|
||||
has_option = False
|
||||
if callback_params is not None:
|
||||
for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
|
||||
if isinstance(callback_param, ParamContext):
|
||||
raise ValueError(_('context is not supported from now for {}').format(path))
|
||||
if isinstance(callback_param, ParamOption):
|
||||
has_option = True
|
||||
if 'expire' in childapi.option.properties():
|
||||
self.tiramisu_web.set_remotable(callback_param.option.impl_getpath(), form)
|
||||
if 'expire' in await childapi.option.properties():
|
||||
await self.tiramisu_web.set_remotable(callback_param.option.impl_getpath(), form)
|
||||
if not has_option and form.get(path, {}).get('remote', False) == False:
|
||||
if 'expire' in childapi.option.properties():
|
||||
self.tiramisu_web.set_remotable(path, form, childapi)
|
||||
elif childapi.owner.isdefault():
|
||||
if 'expire' in await childapi.option.properties():
|
||||
await self.tiramisu_web.set_remotable(path, form, childapi)
|
||||
elif await childapi.owner.isdefault():
|
||||
# get calculated value and set clearable
|
||||
schema[path]['value'] = childapi.value.get()
|
||||
schema[path]['value'] = await childapi.value.get()
|
||||
if self.clearable == 'minimum':
|
||||
form.setdefault(path, {})['clearable'] = True
|
||||
|
||||
@ -89,9 +87,9 @@ class Callbacks(object):
|
||||
# form.setdefault(opt_path, {})
|
||||
# form[opt_path].setdefault('copy', []).append(path)
|
||||
|
||||
def process(self,
|
||||
form):
|
||||
self.process_properties(form)
|
||||
async def process(self,
|
||||
form):
|
||||
await self.process_properties(form)
|
||||
self.manage_callbacks(form)
|
||||
|
||||
|
||||
@ -100,10 +98,10 @@ class Consistencies(object):
|
||||
self.not_equal = {}
|
||||
self.tiramisu_web = tiramisu_web
|
||||
|
||||
def add(self, path, childapi, form):
|
||||
async def add(self, path, childapi, form):
|
||||
return
|
||||
if not childapi.option.isoptiondescription():
|
||||
for consistency in childapi.option.consistencies():
|
||||
if not await childapi.option.isoptiondescription():
|
||||
for consistency in await childapi.option.consistencies():
|
||||
cons_id, func, all_cons_opts, params = consistency
|
||||
if func == '_cons_not_equal' and params.get('transitive', True) is True:
|
||||
options_path = []
|
||||
@ -117,9 +115,9 @@ class Consistencies(object):
|
||||
self.not_equal.setdefault(option._path, {}).setdefault(warnings_only, []).extend(paths)
|
||||
else:
|
||||
for option in all_cons_opts:
|
||||
self.tiramisu_web.set_remotable(option()._path, form)
|
||||
await self.tiramisu_web.set_remotable(option()._path, form)
|
||||
|
||||
def process(self, form):
|
||||
async def process(self, form):
|
||||
for path in self.not_equal:
|
||||
if self.tiramisu_web.is_remote(path, form):
|
||||
continue
|
||||
@ -142,23 +140,23 @@ class Requires(object):
|
||||
self.tiramisu_web = tiramisu_web
|
||||
self.action_hide = self.tiramisu_web.config._config_bag.properties
|
||||
|
||||
def set_master_remote(self, childapi, path, form):
|
||||
if childapi.option.isoptiondescription():
|
||||
async def set_master_remote(self, childapi, path, form):
|
||||
if await childapi.option.isoptiondescription():
|
||||
isfollower = False
|
||||
else:
|
||||
isfollower = childapi.option.isfollower()
|
||||
isfollower = await childapi.option.isfollower()
|
||||
if isfollower:
|
||||
parent_path = path.rsplit('.', 1)[0]
|
||||
parent = self.tiramisu_web.config.unrestraint.option(parent_path)
|
||||
leader = next(parent.list())
|
||||
self.tiramisu_web.set_remotable(leader.option.path(), form, leader)
|
||||
parent = await self.tiramisu_web.config.unrestraint.option(parent_path)
|
||||
leader = await parent.list()[0]
|
||||
await self.tiramisu_web.set_remotable(await leader.option.path(), form, leader)
|
||||
|
||||
def manage_requires(self,
|
||||
childapi,
|
||||
path,
|
||||
form,
|
||||
current_action):
|
||||
for requires in childapi.option.properties(uncalculated=True):
|
||||
async def manage_requires(self,
|
||||
childapi,
|
||||
path,
|
||||
form,
|
||||
current_action):
|
||||
for requires in await childapi.option.properties(uncalculated=True):
|
||||
if not isinstance(requires, str):
|
||||
option = requires.params.kwargs['condition'].option
|
||||
expected = [requires.params.kwargs['expected'].value]
|
||||
@ -180,8 +178,8 @@ class Requires(object):
|
||||
if isinstance(option, tuple):
|
||||
for option_param in chain(option[1].args, option[1].kwargs.values()):
|
||||
if isinstance(option_param, ParamOption):
|
||||
self.tiramisu_web.set_remotable(option_param.option.impl_getpath(), form)
|
||||
self.set_master_remote(childapi, path, form)
|
||||
await self.tiramisu_web.set_remotable(option_param.option.impl_getpath(), form)
|
||||
await self.set_master_remote(childapi, path, form)
|
||||
# elif len_to_long:
|
||||
# self.tiramisu_web.set_remotable(option.impl_getpath(), form)
|
||||
# self.set_master_remote(childapi, path, form)
|
||||
@ -193,8 +191,8 @@ class Requires(object):
|
||||
# transitive to "False" not supported yet for a requirement
|
||||
# same_action to "False" not supported yet for a requirement
|
||||
# operator "and" not supported yet for a requirement
|
||||
self.tiramisu_web.set_remotable(option_path, form, require_option)
|
||||
self.set_master_remote(childapi, path, form)
|
||||
await self.tiramisu_web.set_remotable(option_path, form, require_option)
|
||||
await self.set_master_remote(childapi, path, form)
|
||||
# if require_option.option.requires():
|
||||
# for reqs in require_option.option.requires():
|
||||
# for req in reqs:
|
||||
@ -210,10 +208,10 @@ class Requires(object):
|
||||
inv_act = 'show'
|
||||
if isinstance(option, ChoiceOption):
|
||||
require_option = self.tiramisu_web.config.unrestraint.option(option_path)
|
||||
values = self.tiramisu_web.get_enum(require_option,
|
||||
require_option.option.ismulti(),
|
||||
option_path,
|
||||
require_option.option.properties())
|
||||
values = await self.tiramisu_web.get_enum(require_option,
|
||||
await require_option.option.ismulti(),
|
||||
option_path,
|
||||
await require_option.option.properties())
|
||||
for value in values:
|
||||
if value not in expected:
|
||||
self.requires.setdefault(path,
|
||||
@ -224,8 +222,8 @@ class Requires(object):
|
||||
if current_action is None:
|
||||
current_action = action
|
||||
elif current_action != action:
|
||||
self.tiramisu_web.set_remotable(option_path, form)
|
||||
self.set_master_remote(childapi, path, form)
|
||||
await self.tiramisu_web.set_remotable(option_path, form)
|
||||
await self.set_master_remote(childapi, path, form)
|
||||
for exp in expected:
|
||||
self.requires.setdefault(path,
|
||||
{'expected': {}}
|
||||
@ -234,29 +232,29 @@ class Requires(object):
|
||||
[]).append(option_path)
|
||||
self.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path)
|
||||
else:
|
||||
self.tiramisu_web.set_remotable(option_path, form)
|
||||
self.set_master_remote(childapi, path, form)
|
||||
await self.tiramisu_web.set_remotable(option_path, form)
|
||||
await self.set_master_remote(childapi, path, form)
|
||||
|
||||
def add(self, path, childapi, form):
|
||||
async def add(self, path, childapi, form):
|
||||
#collect id of all options
|
||||
child = childapi.option.get()
|
||||
child = await childapi.option.get()
|
||||
if isinstance(child, SynDynOption):
|
||||
child = child._impl_getopt()
|
||||
self.options[child] = path
|
||||
current_action = None
|
||||
|
||||
self.manage_requires(childapi,
|
||||
path,
|
||||
form,
|
||||
current_action)
|
||||
await self.manage_requires(childapi,
|
||||
path,
|
||||
form,
|
||||
current_action)
|
||||
|
||||
def process(self, form):
|
||||
async def process(self, form):
|
||||
dependencies = {}
|
||||
for path, values in self.requires.items():
|
||||
if 'default' in values:
|
||||
for option in values['default'].get('show', []):
|
||||
if path == option:
|
||||
self.tiramisu_web.set_remotable(path, form)
|
||||
await self.tiramisu_web.set_remotable(path, form)
|
||||
if not self.tiramisu_web.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'default': {}, 'expected': {}}
|
||||
@ -265,7 +263,7 @@ class Requires(object):
|
||||
dependencies[option]['default']['show'].append(path)
|
||||
for option in values['default'].get('hide', []):
|
||||
if path == option:
|
||||
self.tiramisu_web.set_remotable(path, form)
|
||||
await self.tiramisu_web.set_remotable(path, form)
|
||||
if not self.tiramisu_web.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'default': {}, 'expected': {}}
|
||||
@ -277,7 +275,7 @@ class Requires(object):
|
||||
expected = ''
|
||||
for option in actions.get('show', []):
|
||||
if path == option:
|
||||
self.tiramisu_web.set_remotable(path, form)
|
||||
await self.tiramisu_web.set_remotable(path, form)
|
||||
if not self.tiramisu_web.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'expected': {}}
|
||||
@ -287,7 +285,7 @@ class Requires(object):
|
||||
dependencies[option]['expected'][expected]['show'].append(path)
|
||||
for option in actions.get('hide', []):
|
||||
if path == option:
|
||||
self.tiramisu_web.set_remotable(path, form)
|
||||
await self.tiramisu_web.set_remotable(path, form)
|
||||
if not self.tiramisu_web.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'expected': {}}
|
||||
@ -329,24 +327,24 @@ class TiramisuDict:
|
||||
self.clearable = clearable
|
||||
#all, minimum, none
|
||||
self.remotable = remotable
|
||||
self.context_properties = self.config.property.get()
|
||||
self.context_permissives = self.config.permissive.get()
|
||||
|
||||
def add_help(self,
|
||||
obj,
|
||||
childapi):
|
||||
hlp = childapi.information.get('help', None)
|
||||
async def add_help(self,
|
||||
obj,
|
||||
childapi):
|
||||
hlp = await childapi.information.get('help', None)
|
||||
if hlp is not None:
|
||||
obj['help'] = hlp
|
||||
|
||||
def get_list(self, root, subchildapi):
|
||||
for childapi in subchildapi.list('all'):
|
||||
childname = childapi.option.name()
|
||||
async def get_list(self, root, subchildapi):
|
||||
ret = []
|
||||
for childapi in await subchildapi.list('all'):
|
||||
childname = await childapi.option.name()
|
||||
if root is None:
|
||||
path = childname
|
||||
else:
|
||||
path = root + '.' + childname
|
||||
yield path, childapi
|
||||
ret.append((path, childapi))
|
||||
return ret
|
||||
|
||||
def is_remote(self, path, form):
|
||||
if self.remotable == 'all':
|
||||
@ -354,27 +352,27 @@ class TiramisuDict:
|
||||
else:
|
||||
return path in form and form[path].get('remote', False) == True
|
||||
|
||||
def set_remotable(self, path, form, childapi=None):
|
||||
async def set_remotable(self, path, form, childapi=None):
|
||||
if self.remotable == 'none':
|
||||
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
|
||||
form.setdefault(path, {})['remote'] = True
|
||||
if childapi is None:
|
||||
childapi = self.config.unrestraint.option(path)
|
||||
if childapi.option.isfollower():
|
||||
if await childapi.option.isfollower():
|
||||
parent_path = path.rsplit('.', 1)[0]
|
||||
parent = self.config.unrestraint.option(parent_path)
|
||||
leader = next(parent.list())
|
||||
form.setdefault(leader.option.path(), {})['remote'] = True
|
||||
parent = await self.config.unrestraint.option(parent_path)
|
||||
leader = await parent.list()[0]
|
||||
form.setdefault(await leader.option.path(), {})['remote'] = True
|
||||
|
||||
def walk(self,
|
||||
root,
|
||||
subchildapi,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=False):
|
||||
async def walk(self,
|
||||
root,
|
||||
subchildapi,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=False):
|
||||
error = None
|
||||
if init:
|
||||
if form is not None:
|
||||
@ -391,36 +389,36 @@ class TiramisuDict:
|
||||
subchildapi = self.config.unrestraint.option(root)
|
||||
isleadership = False
|
||||
else:
|
||||
isleadership = subchildapi.option.isleadership()
|
||||
isleadership = await subchildapi.option.isleadership()
|
||||
leader_len = None
|
||||
for path, childapi in self.get_list(root, subchildapi):
|
||||
for path, childapi in await self.get_list(root, subchildapi):
|
||||
if isleadership and leader_len is None:
|
||||
leader_len = childapi.value.len()
|
||||
leader_len = await childapi.value.len()
|
||||
one_is_remote = False
|
||||
props_no_requires = set(childapi.option.properties())
|
||||
props_no_requires = set(await childapi.option.properties())
|
||||
if form is not None:
|
||||
self.requires.add(path,
|
||||
childapi,
|
||||
form)
|
||||
self.consistencies.add(path,
|
||||
childapi,
|
||||
form)
|
||||
self.callbacks.add(path,
|
||||
childapi,
|
||||
schema,
|
||||
'force_store_value' in props_no_requires)
|
||||
await self.requires.add(path,
|
||||
childapi,
|
||||
form)
|
||||
await self.consistencies.add(path,
|
||||
childapi,
|
||||
form)
|
||||
await self.callbacks.add(path,
|
||||
childapi,
|
||||
schema,
|
||||
'force_store_value' in props_no_requires)
|
||||
childapi_option = childapi.option
|
||||
if model is not None and childapi.option.isoptiondescription() or not childapi_option.issymlinkoption():
|
||||
self.gen_model(model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
updates_status)
|
||||
if model is not None and await childapi.option.isoptiondescription() or not await childapi_option.issymlinkoption():
|
||||
await self.gen_model(model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
updates_status)
|
||||
if order is not None:
|
||||
order.append(path)
|
||||
if childapi.option.isoptiondescription():
|
||||
if await childapi.option.isoptiondescription():
|
||||
web_type = 'optiondescription'
|
||||
if childapi_option.isleadership():
|
||||
if await childapi_option.isleadership():
|
||||
type_ = 'array'
|
||||
else:
|
||||
type_ = 'object'
|
||||
@ -430,60 +428,60 @@ class TiramisuDict:
|
||||
subschema = schema[path]['properties']
|
||||
else:
|
||||
subschema = schema
|
||||
self.walk(path,
|
||||
childapi,
|
||||
subschema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status)
|
||||
await self.walk(path,
|
||||
childapi,
|
||||
subschema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status)
|
||||
else:
|
||||
child = childapi_option.get()
|
||||
child = await childapi_option.get()
|
||||
childtype = child.__class__.__name__
|
||||
if childtype == 'SynDynOption':
|
||||
childtype = child._impl_getopt().__class__.__name__
|
||||
if childapi_option.issymlinkoption():
|
||||
if await childapi_option.issymlinkoption():
|
||||
web_type = 'symlink'
|
||||
value = None
|
||||
defaultmulti = None
|
||||
is_multi = False
|
||||
else:
|
||||
web_type = childapi_option.type()
|
||||
value = childapi.option.default()
|
||||
web_type = await childapi_option.type()
|
||||
value = await childapi.option.default()
|
||||
if value == []:
|
||||
value = None
|
||||
|
||||
is_multi = childapi_option.ismulti()
|
||||
is_multi = await childapi_option.ismulti()
|
||||
if is_multi:
|
||||
defaultmulti = childapi_option.defaultmulti()
|
||||
defaultmulti = await childapi_option.defaultmulti()
|
||||
if defaultmulti == []:
|
||||
defaultmulti = None
|
||||
else:
|
||||
defaultmulti = None
|
||||
|
||||
if schema is not None:
|
||||
self.gen_schema(schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
defaultmulti,
|
||||
is_multi,
|
||||
web_type,
|
||||
form)
|
||||
await self.gen_schema(schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
defaultmulti,
|
||||
is_multi,
|
||||
web_type,
|
||||
form)
|
||||
if form is not None:
|
||||
self.gen_form(form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype)
|
||||
await self.gen_form(form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype)
|
||||
if schema is not None:
|
||||
if web_type != 'symlink':
|
||||
schema[path]['title'] = childapi_option.description()
|
||||
self.add_help(schema[path],
|
||||
childapi)
|
||||
schema[path]['title'] = await childapi_option.description()
|
||||
await self.add_help(schema[path],
|
||||
childapi)
|
||||
except Exception as err:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@ -491,9 +489,9 @@ class TiramisuDict:
|
||||
raise err
|
||||
error = err
|
||||
if init and form is not None:
|
||||
self.callbacks.process(form)
|
||||
self.requires.process(form)
|
||||
self.consistencies.process(form)
|
||||
await self.callbacks.process(form)
|
||||
await self.requires.process(form)
|
||||
await self.consistencies.process(form)
|
||||
del self.requires
|
||||
del self.consistencies
|
||||
del self.callbacks
|
||||
@ -503,20 +501,21 @@ class TiramisuDict:
|
||||
raise ConfigError(_('unable to transform tiramisu object to dict: {}').format(msg))
|
||||
|
||||
|
||||
def gen_schema(self,
|
||||
schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
defaultmulti,
|
||||
is_multi,
|
||||
web_type,
|
||||
form):
|
||||
async def gen_schema(self,
|
||||
schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
defaultmulti,
|
||||
is_multi,
|
||||
web_type,
|
||||
form):
|
||||
schema[path] = {'type': web_type}
|
||||
if childapi_option.issymlinkoption():
|
||||
schema[path]['opt_path'] = childapi_option.get().impl_getopt().impl_getpath()
|
||||
if await childapi_option.issymlinkoption():
|
||||
sym_option = await childapi_option.get()
|
||||
schema[path]['opt_path'] = sym_option.impl_getopt().impl_getpath()
|
||||
else:
|
||||
if defaultmulti is not None:
|
||||
schema[path]['defaultmulti'] = defaultmulti
|
||||
@ -524,7 +523,7 @@ class TiramisuDict:
|
||||
if is_multi:
|
||||
schema[path]['isMulti'] = is_multi
|
||||
|
||||
if childapi_option.issubmulti():
|
||||
if await childapi_option.issubmulti():
|
||||
schema[path]['isSubMulti'] = True
|
||||
|
||||
if 'auto_freeze' in props_no_requires:
|
||||
@ -537,58 +536,56 @@ class TiramisuDict:
|
||||
# if isinstance(values_param, ParamOption):
|
||||
# self.set_remotable(path, form, childapi)
|
||||
# return
|
||||
schema[path]['enum'] = self.get_enum(childapi,
|
||||
is_multi,
|
||||
path,
|
||||
props_no_requires)
|
||||
schema[path]['enum'] = await self.get_enum(childapi,
|
||||
is_multi,
|
||||
path,
|
||||
props_no_requires)
|
||||
if value is not None and not self.is_remote(path, form):
|
||||
schema[path]['value'] = value
|
||||
|
||||
|
||||
def get_enum(self,
|
||||
childapi,
|
||||
is_multi,
|
||||
path,
|
||||
props_no_requires):
|
||||
values = childapi.value.list()
|
||||
empty_is_required = not childapi.option.isfollower() and is_multi
|
||||
async def get_enum(self,
|
||||
childapi,
|
||||
is_multi,
|
||||
path,
|
||||
props_no_requires):
|
||||
values = await childapi.value.list()
|
||||
empty_is_required = not await childapi.option.isfollower() and is_multi
|
||||
if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \
|
||||
(not empty_is_required and not 'mandatory' in props_no_requires)):
|
||||
values = [''] + list(values)
|
||||
return values
|
||||
|
||||
def gen_form(self,
|
||||
form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype):
|
||||
async def gen_form(self,
|
||||
form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype):
|
||||
obj_form = {}
|
||||
if path in form:
|
||||
obj_form.update(form[path])
|
||||
if not childapi_option.issymlinkoption():
|
||||
if not await childapi_option.issymlinkoption():
|
||||
#if childapi_option.validator() != (None, None):
|
||||
# obj_form['remote'] = True
|
||||
# params = childapi_option.validator()[1]
|
||||
# if params is not None:
|
||||
# for param in chain(params.args, params.kwargs.values()):
|
||||
# if isinstance(param, ParamContext):
|
||||
# raise ValueError(_('context is not supported from now for {}').format(path))
|
||||
# if isinstance(param, ParamOption):
|
||||
# self.set_remotable(param.option.impl_getpath(), form)
|
||||
if self.clearable == 'all':
|
||||
obj_form['clearable'] = True
|
||||
if self.clearable != 'none':
|
||||
obj_form['clearable'] = True
|
||||
if self.remotable == 'all' or childapi_option.has_dependency():
|
||||
if self.remotable == 'all' or await childapi_option.has_dependency():
|
||||
obj_form['remote'] = True
|
||||
if childtype == 'IPOption' and (child.impl_get_extra('_private_only') or not child.impl_get_extra('_allow_reserved') or child.impl_get_extra('_cidr')):
|
||||
obj_form['remote'] = True
|
||||
if childtype == 'DateOption':
|
||||
obj_form['remote'] = True
|
||||
if not obj_form.get('remote', False):
|
||||
pattern = childapi_option.pattern()
|
||||
pattern = await childapi_option.pattern()
|
||||
if pattern is not None:
|
||||
obj_form['pattern'] = pattern
|
||||
if childtype == 'PortOption':
|
||||
@ -603,42 +600,36 @@ class TiramisuDict:
|
||||
if obj_form:
|
||||
form[path] = obj_form
|
||||
|
||||
def calc_raises_properties(self,
|
||||
obj,
|
||||
childapi):
|
||||
async def calc_raises_properties(self,
|
||||
obj,
|
||||
childapi):
|
||||
old_properties = childapi._option_bag.config_bag.properties
|
||||
del childapi._option_bag.config_bag.properties
|
||||
has_permissive = 'permissive' in childapi._option_bag.config_bag.properties
|
||||
if not has_permissive:
|
||||
childapi._option_bag.config_bag.properties = childapi._option_bag.config_bag.properties | {'permissive'}
|
||||
# 'display=False' means cannot access only without permissive option
|
||||
config = childapi._option_bag.config_bag.context
|
||||
settings = config.cfgimpl_get_settings()
|
||||
childapi._option_bag.config_bag.properties = await settings.get_context_properties(config._impl_properties_cache)
|
||||
childapi._option_bag.config_bag.properties -= {'permissive'}
|
||||
properties = await childapi.property.get(only_raises=True)
|
||||
properties -= await childapi.permissive.get()
|
||||
# 'hidden=True' means cannot access with or without permissive option
|
||||
properties = childapi.property.get(only_raises=True)
|
||||
if has_permissive:
|
||||
properties -= self.config.permissive.get()
|
||||
properties -= childapi.permissive.get()
|
||||
if properties:
|
||||
obj['hidden'] = True
|
||||
childapi._option_bag.config_bag.properties = childapi._option_bag.config_bag.properties - {'permissive'}
|
||||
properties = childapi.property.get(only_raises=True)
|
||||
if has_permissive:
|
||||
properties -= self.config.permissive.get()
|
||||
properties -= childapi.permissive.get()
|
||||
# 'display=False' means cannot access only without permissive option
|
||||
if properties:
|
||||
obj['display'] = False
|
||||
properties -= await self.config.permissive.get()
|
||||
if properties:
|
||||
obj['hidden'] = True
|
||||
childapi._option_bag.config_bag.properties = old_properties
|
||||
|
||||
def _gen_model_properties(self,
|
||||
childapi,
|
||||
path,
|
||||
index):
|
||||
isfollower = childapi.option.isfollower()
|
||||
props = set(childapi.property.get())
|
||||
async def _gen_model_properties(self,
|
||||
childapi,
|
||||
path,
|
||||
index):
|
||||
isfollower = await childapi.option.isfollower()
|
||||
props = set(await childapi.property.get())
|
||||
obj = self.gen_properties(props,
|
||||
isfollower,
|
||||
childapi.option.ismulti(),
|
||||
await childapi.option.ismulti(),
|
||||
index)
|
||||
self.calc_raises_properties(obj, childapi)
|
||||
await self.calc_raises_properties(obj, childapi)
|
||||
return obj
|
||||
|
||||
def gen_properties(self,
|
||||
@ -674,61 +665,61 @@ class TiramisuDict:
|
||||
obj['properties'] = lprops
|
||||
return obj
|
||||
|
||||
def gen_model(self,
|
||||
model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
updates_status):
|
||||
if childapi.option.isoptiondescription():
|
||||
props = set(childapi.property.get())
|
||||
async def gen_model(self,
|
||||
model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
updates_status):
|
||||
if await childapi.option.isoptiondescription():
|
||||
props = set(await childapi.property.get())
|
||||
obj = {}
|
||||
self.calc_raises_properties(obj, childapi)
|
||||
await self.calc_raises_properties(obj, childapi)
|
||||
if props:
|
||||
lprops = list(props)
|
||||
lprops.sort()
|
||||
obj['properties'] = lprops
|
||||
try:
|
||||
self.config.option(path).option.get()
|
||||
await self.config.option(path).option.get()
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
else:
|
||||
obj = self._gen_model_properties(childapi,
|
||||
path,
|
||||
None)
|
||||
if childapi.option.isfollower():
|
||||
obj = await self._gen_model_properties(childapi,
|
||||
path,
|
||||
None)
|
||||
if await childapi.option.isfollower():
|
||||
for index in range(leader_len):
|
||||
follower_childapi = self.config.unrestraint.option(path, index)
|
||||
sobj = self._gen_model_properties(follower_childapi,
|
||||
path,
|
||||
index)
|
||||
self._get_model_value(follower_childapi,
|
||||
path,
|
||||
sobj,
|
||||
index,
|
||||
updates_status)
|
||||
sobj = await self._gen_model_properties(follower_childapi,
|
||||
path,
|
||||
index)
|
||||
await self._get_model_value(follower_childapi,
|
||||
path,
|
||||
sobj,
|
||||
index,
|
||||
updates_status)
|
||||
if sobj:
|
||||
model.setdefault(path, {})[str(index)] = sobj
|
||||
else:
|
||||
self._get_model_value(childapi,
|
||||
path,
|
||||
obj,
|
||||
None,
|
||||
updates_status)
|
||||
await self._get_model_value(childapi,
|
||||
path,
|
||||
obj,
|
||||
None,
|
||||
updates_status)
|
||||
if obj:
|
||||
if not childapi.option.isoptiondescription() and childapi.option.isfollower():
|
||||
if not await childapi.option.isoptiondescription() and await childapi.option.isfollower():
|
||||
model.setdefault(path, {})['null'] = obj
|
||||
else:
|
||||
model[path] = obj
|
||||
|
||||
def _get_model_value(self,
|
||||
childapi,
|
||||
path,
|
||||
obj,
|
||||
index,
|
||||
updates_status):
|
||||
async def _get_model_value(self,
|
||||
childapi,
|
||||
path,
|
||||
obj,
|
||||
index,
|
||||
updates_status):
|
||||
if path in updates_status and index in updates_status[path]:
|
||||
value = childapi.value.get()
|
||||
value = await childapi.value.get()
|
||||
self._get_value_with_exception(obj,
|
||||
childapi,
|
||||
updates_status[path][index])
|
||||
@ -736,7 +727,7 @@ class TiramisuDict:
|
||||
else:
|
||||
try:
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
value = self.config.option(path, index=index).value.get()
|
||||
value = await self.config.option(path, index=index).value.get()
|
||||
self._get_value_with_exception(obj,
|
||||
childapi,
|
||||
warns)
|
||||
@ -744,7 +735,7 @@ class TiramisuDict:
|
||||
self._get_value_with_exception(obj,
|
||||
childapi,
|
||||
[err])
|
||||
value = self.config.unrestraint.option(path, index=index).value.get()
|
||||
value = await self.config.unrestraint.option(path, index=index).value.get()
|
||||
except PropertiesOptionError as err:
|
||||
config_bag = self.config._config_bag
|
||||
settings = config_bag.context.cfgimpl_get_settings()
|
||||
@ -753,11 +744,11 @@ class TiramisuDict:
|
||||
set(err.proptype)):
|
||||
obj['hidden'] = True
|
||||
obj['display'] = False
|
||||
value = childapi.value.get()
|
||||
value = await childapi.value.get()
|
||||
if value is not None and value != []:
|
||||
obj['value'] = value
|
||||
if not childapi.owner.isdefault():
|
||||
obj['owner'] = childapi.owner.get()
|
||||
if not await childapi.owner.isdefault():
|
||||
obj['owner'] = await childapi.owner.get()
|
||||
|
||||
def _get_value_with_exception(self,
|
||||
obj,
|
||||
@ -785,12 +776,12 @@ class TiramisuDict:
|
||||
obj['warnings'].append(msg)
|
||||
obj['hasWarnings'] = True
|
||||
|
||||
def gen_global(self):
|
||||
async def gen_global(self):
|
||||
ret = {}
|
||||
ret['owner'] = self.config.owner.get()
|
||||
ret['properties'] = list(self.config.property.get())
|
||||
ret['owner'] = await self.config.owner.get()
|
||||
ret['properties'] = list(await self.config.property.get())
|
||||
ret['properties'].sort()
|
||||
ret['permissives'] = list(self.config.permissive.get())
|
||||
ret['permissives'] = list(await self.config.permissive.get())
|
||||
ret['permissives'].sort()
|
||||
return ret
|
||||
|
||||
@ -816,36 +807,36 @@ class TiramisuDict:
|
||||
ret.extend(buttons)
|
||||
return ret
|
||||
|
||||
def del_value(self, childapi, path, index):
|
||||
if index is not None and childapi.option.isleader():
|
||||
childapi.value.pop(index)
|
||||
elif index is None or childapi.option.isfollower():
|
||||
childapi.value.reset()
|
||||
async def del_value(self, childapi, path, index):
|
||||
if index is not None and await childapi.option.isleader():
|
||||
await childapi.value.pop(index)
|
||||
elif index is None or await childapi.option.isfollower():
|
||||
await childapi.value.reset()
|
||||
else:
|
||||
multi = childapi.value.get()
|
||||
multi = await childapi.value.get()
|
||||
multi.pop(index)
|
||||
childapi.value.set(multi)
|
||||
await childapi.value.set(multi)
|
||||
|
||||
def add_value(self, childapi, path, value):
|
||||
multi = childapi.value.get()
|
||||
async def add_value(self, childapi, path, value):
|
||||
multi = await childapi.value.get()
|
||||
multi.append(value)
|
||||
childapi.value.set(multi)
|
||||
await childapi.value.set(multi)
|
||||
|
||||
def mod_value(self, childapi, path, index, value):
|
||||
if index is None or childapi.option.isfollower():
|
||||
childapi.value.set(value)
|
||||
async def mod_value(self, childapi, path, index, value):
|
||||
if index is None or await childapi.option.isfollower():
|
||||
await childapi.value.set(value)
|
||||
else:
|
||||
multi = childapi.value.get()
|
||||
multi = await childapi.value.get()
|
||||
if len(multi) < index + 1:
|
||||
multi.append(value)
|
||||
else:
|
||||
multi[index] = value
|
||||
childapi.value.set(multi)
|
||||
await childapi.value.set(multi)
|
||||
|
||||
def apply_updates(self,
|
||||
oripath,
|
||||
updates,
|
||||
model_ori):
|
||||
async def apply_updates(self,
|
||||
oripath,
|
||||
updates,
|
||||
model_ori):
|
||||
updates_status = {}
|
||||
for update in updates:
|
||||
path = update['name']
|
||||
@ -854,22 +845,22 @@ class TiramisuDict:
|
||||
raise ValueError(_('not in current area'))
|
||||
childapi = self.config.option(path)
|
||||
childapi_option = childapi.option
|
||||
if childapi_option.isfollower():
|
||||
if await childapi_option.isfollower():
|
||||
childapi = self.config.option(path, index)
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
try:
|
||||
if update['action'] == 'modify':
|
||||
self.mod_value(childapi,
|
||||
path,
|
||||
index,
|
||||
update.get('value', undefined))
|
||||
await self.mod_value(childapi,
|
||||
path,
|
||||
index,
|
||||
update.get('value', undefined))
|
||||
elif update['action'] == 'delete':
|
||||
self.del_value(childapi,
|
||||
path,
|
||||
index)
|
||||
await self.del_value(childapi,
|
||||
path,
|
||||
index)
|
||||
elif update['action'] == 'add':
|
||||
if childapi_option.ismulti():
|
||||
self.add_value(childapi, path, update['value'])
|
||||
if await childapi_option.ismulti():
|
||||
await self.add_value(childapi, path, update['value'])
|
||||
else:
|
||||
raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path))
|
||||
else:
|
||||
@ -880,33 +871,33 @@ class TiramisuDict:
|
||||
updates_status.setdefault(path, {}).setdefault(index, []).extend(warns)
|
||||
return updates_status
|
||||
|
||||
def set_updates(self,
|
||||
body):
|
||||
async def set_updates(self,
|
||||
body):
|
||||
root_path = self.root
|
||||
updates = body.get('updates', [])
|
||||
updates_status = self.apply_updates(root_path,
|
||||
updates,
|
||||
body.get('model'))
|
||||
updates_status = await self.apply_updates(root_path,
|
||||
updates,
|
||||
body.get('model'))
|
||||
if 'model' in body:
|
||||
order = []
|
||||
old_model = body['model']
|
||||
new_model = self.todict(order=order,
|
||||
build_schema=False,
|
||||
build_form=False,
|
||||
updates_status=updates_status)['model']
|
||||
values = {'updates': list_keys(old_model, new_model, order, updates_status),
|
||||
'model': new_model}
|
||||
new_model = await self.todict(order=order,
|
||||
build_schema=False,
|
||||
build_form=False,
|
||||
updates_status=updates_status)
|
||||
values = {'updates': list_keys(old_model, new_model['model'], order, updates_status),
|
||||
'model': new_model['model']}
|
||||
else:
|
||||
values = updates_status
|
||||
return values
|
||||
|
||||
def todict(self,
|
||||
custom_form=[],
|
||||
build_schema=True,
|
||||
build_model=True,
|
||||
build_form=True,
|
||||
order=None,
|
||||
updates_status={}):
|
||||
async def todict(self,
|
||||
custom_form=[],
|
||||
build_schema=True,
|
||||
build_model=True,
|
||||
build_form=True,
|
||||
order=None,
|
||||
updates_status={}):
|
||||
rootpath = self.root
|
||||
if build_schema:
|
||||
schema = {}
|
||||
@ -921,14 +912,14 @@ class TiramisuDict:
|
||||
buttons = []
|
||||
else:
|
||||
form = None
|
||||
self.walk(rootpath,
|
||||
None,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=True)
|
||||
await self.walk(rootpath,
|
||||
None,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=True)
|
||||
if build_form:
|
||||
for form_ in custom_form:
|
||||
if 'key' in form_:
|
||||
@ -944,7 +935,7 @@ class TiramisuDict:
|
||||
ret['schema'] = schema
|
||||
if build_model:
|
||||
ret['model'] = model
|
||||
ret['global'] = self.gen_global()
|
||||
ret['global'] = await self.gen_global()
|
||||
if build_form:
|
||||
ret['form'] = form
|
||||
ret['version'] = '1.0'
|
||||
|
@ -21,9 +21,11 @@ from .error import ConfigError, PropertiesOptionError
|
||||
from .setting import owners, undefined, forbidden_owners, OptionBag, ConfigBag
|
||||
from .autolib import Calculation, carry_out_calculation, Params
|
||||
from .i18n import _
|
||||
from .asyncinit import asyncinit
|
||||
|
||||
|
||||
class Values(object):
|
||||
@asyncinit
|
||||
class Values:
|
||||
"""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.
|
||||
@ -31,8 +33,8 @@ class Values(object):
|
||||
__slots__ = ('_p_',
|
||||
'__weakref__')
|
||||
|
||||
def __init__(self,
|
||||
storage):
|
||||
async def __init__(self,
|
||||
storage):
|
||||
"""
|
||||
Initializes the values's dict.
|
||||
|
||||
@ -42,18 +44,19 @@ class Values(object):
|
||||
# store the storage
|
||||
self._p_ = storage
|
||||
# set default owner
|
||||
if self._p_.getowner(None, None) is None:
|
||||
self._p_.setvalue(None,
|
||||
None,
|
||||
owners.user,
|
||||
None,
|
||||
True)
|
||||
owner = await self._p_.getowner(None, None)
|
||||
if owner is None:
|
||||
await self._p_.setvalue(None,
|
||||
None,
|
||||
owners.user,
|
||||
None,
|
||||
True)
|
||||
|
||||
#______________________________________________________________________
|
||||
# get value
|
||||
|
||||
def get_cached_value(self,
|
||||
option_bag):
|
||||
async def get_cached_value(self,
|
||||
option_bag):
|
||||
"""get value directly in cache if set
|
||||
otherwise calculated value and set it in cache
|
||||
|
||||
@ -70,11 +73,11 @@ class Values(object):
|
||||
'value')
|
||||
if not validated:
|
||||
# no cached value so get value
|
||||
value = self.getvalue(option_bag)
|
||||
value = await self.getvalue(option_bag)
|
||||
# validate value
|
||||
option_bag.option.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=True)
|
||||
await option_bag.option.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=True)
|
||||
# store value in cache
|
||||
validator = 'validator' in setting_properties and 'demoting_error_warning' not in setting_properties
|
||||
if not is_cached or validator:
|
||||
@ -85,9 +88,9 @@ class Values(object):
|
||||
setting_properties,
|
||||
validator)
|
||||
if 'warnings' in setting_properties:
|
||||
option_bag.option.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
await option_bag.option.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
if isinstance(value, list):
|
||||
# return a copy, so value cannot be modified
|
||||
from copy import copy
|
||||
@ -95,33 +98,35 @@ class Values(object):
|
||||
# and return it
|
||||
return value
|
||||
|
||||
def force_to_metaconfig(self, option_bag):
|
||||
async def force_to_metaconfig(self, option_bag):
|
||||
# force_metaconfig_on_freeze in config => to metaconfig
|
||||
# force_metaconfig_on_freeze in option + config is kernelconfig => to metaconfig
|
||||
settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
if 'force_metaconfig_on_freeze' in option_bag.properties:
|
||||
settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
if 'force_metaconfig_on_freeze' in option_bag.option.impl_getproperties() and \
|
||||
not settings._p_.getproperties(option_bag.path, None, frozenset()):
|
||||
not await settings._p_.getproperties(option_bag.path, None, frozenset()):
|
||||
# if force_metaconfig_on_freeze is only in option (not in config)
|
||||
return option_bag.config_bag.context.impl_type == 'config'
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _do_value_list(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag):
|
||||
async def _do_value_list(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag):
|
||||
ret = []
|
||||
for val in value:
|
||||
if isinstance(val, (list, tuple)):
|
||||
yield list(self._do_value_list(val, option_bag))
|
||||
ret.append(await self._do_value_list(val, option_bag))
|
||||
elif isinstance(val, Calculation):
|
||||
yield val.execute(option_bag)
|
||||
ret.append(await val.execute(option_bag))
|
||||
else:
|
||||
yield val
|
||||
ret.append(val)
|
||||
return ret
|
||||
|
||||
def getvalue(self,
|
||||
option_bag):
|
||||
async def getvalue(self,
|
||||
option_bag):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param path: the path of the `Option`
|
||||
@ -138,48 +143,52 @@ class Values(object):
|
||||
_index = None
|
||||
else:
|
||||
_index = index
|
||||
owner, value = self._p_.getowner(option_bag.path,
|
||||
owners.default,
|
||||
index=_index,
|
||||
with_value=True)
|
||||
owner, value = await self._p_.getowner(option_bag.path,
|
||||
owners.default,
|
||||
index=_index,
|
||||
with_value=True)
|
||||
if owner == owners.default or \
|
||||
('frozen' in option_bag.properties and \
|
||||
('force_default_on_freeze' in option_bag.properties or self.force_to_metaconfig(option_bag))):
|
||||
value = self.getdefaultvalue(option_bag)
|
||||
('force_default_on_freeze' in option_bag.properties or await self.force_to_metaconfig(option_bag))):
|
||||
value = await self.getdefaultvalue(option_bag)
|
||||
else:
|
||||
value = self.calc_value(option_bag, value)
|
||||
value = await self.calc_value(option_bag, value)
|
||||
return value
|
||||
|
||||
def calc_value(self, option_bag, value, reset_cache=True):
|
||||
async def calc_value(self,
|
||||
option_bag,
|
||||
value,
|
||||
reset_cache=True):
|
||||
if isinstance(value, Calculation):
|
||||
value = value.execute(option_bag, leadership_must_have_index=True)
|
||||
value = await value.execute(option_bag,
|
||||
leadership_must_have_index=True)
|
||||
elif isinstance(value, (list, tuple)):
|
||||
value = list(self._do_value_list(value, option_bag))
|
||||
value = await self._do_value_list(value, option_bag)
|
||||
if reset_cache:
|
||||
self.calculate_reset_cache(option_bag, value)
|
||||
await self.calculate_reset_cache(option_bag, value)
|
||||
return value
|
||||
|
||||
def getdefaultvalue(self,
|
||||
option_bag):
|
||||
async def getdefaultvalue(self,
|
||||
option_bag):
|
||||
"""get default value:
|
||||
- get parents config value or
|
||||
- get calculated value or
|
||||
- get default value
|
||||
"""
|
||||
moption_bag = self._get_modified_parent(option_bag)
|
||||
moption_bag = await self._get_modified_parent(option_bag)
|
||||
if moption_bag is not None:
|
||||
# retrieved value from parent config
|
||||
return moption_bag.config_bag.context.cfgimpl_get_values().get_cached_value(moption_bag)
|
||||
return await moption_bag.config_bag.context.cfgimpl_get_values().get_cached_value(moption_bag)
|
||||
|
||||
if option_bag.option.impl_has_callback():
|
||||
# default value is a calculated value
|
||||
value = self.calculate_value(option_bag)
|
||||
value = await self.calculate_value(option_bag)
|
||||
if value is not undefined:
|
||||
return value
|
||||
|
||||
# now try to get default value:
|
||||
value = self.calc_value(option_bag,
|
||||
option_bag.option.impl_getdefault())
|
||||
value = await self.calc_value(option_bag,
|
||||
option_bag.option.impl_getdefault())
|
||||
if option_bag.option.impl_is_multi() and option_bag.index is not None and isinstance(value, (list, tuple)):
|
||||
# if index, must return good value for this index
|
||||
if len(value) > option_bag.index:
|
||||
@ -187,11 +196,13 @@ class Values(object):
|
||||
else:
|
||||
# no value for this index, retrieve default multi value
|
||||
# default_multi is already a list for submulti
|
||||
value = self.calc_value(option_bag,
|
||||
value = await self.calc_value(option_bag,
|
||||
option_bag.option.impl_getdefault_multi())
|
||||
return value
|
||||
|
||||
def calculate_reset_cache(self, option_bag, value):
|
||||
async def calculate_reset_cache(self,
|
||||
option_bag,
|
||||
value):
|
||||
if not 'expire' in option_bag.properties:
|
||||
return
|
||||
cache = option_bag.config_bag.context._impl_values_cache
|
||||
@ -206,25 +217,25 @@ class Values(object):
|
||||
# so do not invalidate cache
|
||||
return
|
||||
# calculated value is a new value, so reset cache
|
||||
option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
await option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
|
||||
def calculate_value(self,
|
||||
option_bag: OptionBag) -> Any:
|
||||
async def calculate_value(self,
|
||||
option_bag: OptionBag) -> Any:
|
||||
|
||||
# if value has callback, calculate value
|
||||
callback, callback_params = option_bag.option.impl_get_callback()
|
||||
value = self.carry_out_calculation(option_bag,
|
||||
callback,
|
||||
callback_params)
|
||||
value = await self.carry_out_calculation(option_bag,
|
||||
callback,
|
||||
callback_params)
|
||||
if isinstance(value, list) and option_bag.index is not None:
|
||||
# if value is a list and index is set
|
||||
if option_bag.option.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
|
||||
self.calculate_reset_cache(option_bag, value)
|
||||
await self.calculate_reset_cache(option_bag, value)
|
||||
return value
|
||||
if len(value) > option_bag.index:
|
||||
# return the value for specified index if found
|
||||
self.calculate_reset_cache(option_bag, value[option_bag.index])
|
||||
await self.calculate_reset_cache(option_bag, value[option_bag.index])
|
||||
return value[option_bag.index]
|
||||
# there is no calculate value for this index,
|
||||
# so return an other default value
|
||||
@ -244,19 +255,19 @@ class Values(object):
|
||||
elif option_bag.option.impl_is_multi() and not isinstance(value, list) and option_bag.index is None:
|
||||
# return a list for a multi
|
||||
value = [value]
|
||||
self.calculate_reset_cache(option_bag, value)
|
||||
await self.calculate_reset_cache(option_bag, value)
|
||||
return value
|
||||
return undefined
|
||||
|
||||
def carry_out_calculation(self,
|
||||
option_bag: OptionBag,
|
||||
callback: Callable,
|
||||
callback_params: Optional[Params]) -> Any:
|
||||
return carry_out_calculation(option_bag.option,
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag)
|
||||
async def carry_out_calculation(self,
|
||||
option_bag: OptionBag,
|
||||
callback: Callable,
|
||||
callback_params: Optional[Params]) -> Any:
|
||||
return await carry_out_calculation(option_bag.option,
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
index=option_bag.index,
|
||||
config_bag=option_bag.config_bag)
|
||||
def isempty(self,
|
||||
opt,
|
||||
value,
|
||||
@ -273,23 +284,23 @@ class Values(object):
|
||||
|
||||
#______________________________________________________________________
|
||||
# set value
|
||||
def setvalue(self,
|
||||
value,
|
||||
option_bag,
|
||||
_commit):
|
||||
async def setvalue(self,
|
||||
value,
|
||||
option_bag,
|
||||
_commit):
|
||||
context = option_bag.config_bag.context
|
||||
owner = self.get_context_owner()
|
||||
owner = await self.get_context_owner()
|
||||
if 'validator' in option_bag.config_bag.properties:
|
||||
self.setvalue_validation(value,
|
||||
option_bag)
|
||||
await self.setvalue_validation(value,
|
||||
option_bag)
|
||||
|
||||
if isinstance(value, list):
|
||||
# copy
|
||||
value = value.copy()
|
||||
self._setvalue(option_bag,
|
||||
value,
|
||||
owner,
|
||||
commit=False)
|
||||
await self._setvalue(option_bag,
|
||||
value,
|
||||
owner,
|
||||
commit=False)
|
||||
setting_properties = option_bag.config_bag.properties
|
||||
validator = 'validator' in setting_properties and 'demoting_error_warning' not in setting_properties
|
||||
if validator:
|
||||
@ -301,48 +312,48 @@ class Values(object):
|
||||
setting_properties,
|
||||
validator)
|
||||
if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader():
|
||||
option_bag.option.impl_get_leadership().follower_force_store_value(self,
|
||||
value,
|
||||
option_bag,
|
||||
owners.forced,
|
||||
_commit=_commit)
|
||||
await option_bag.option.impl_get_leadership().follower_force_store_value(self,
|
||||
value,
|
||||
option_bag,
|
||||
owners.forced,
|
||||
_commit=_commit)
|
||||
if _commit:
|
||||
self._p_.commit()
|
||||
await self._p_.commit()
|
||||
|
||||
def setvalue_validation(self,
|
||||
value,
|
||||
option_bag):
|
||||
async def setvalue_validation(self,
|
||||
value,
|
||||
option_bag):
|
||||
settings = option_bag.config_bag.context.cfgimpl_get_settings()
|
||||
# First validate properties with this value
|
||||
opt = option_bag.option
|
||||
settings.validate_frozen(option_bag)
|
||||
val = self.calc_value(option_bag, value, False)
|
||||
val = await self.calc_value(option_bag, value, False)
|
||||
settings.validate_mandatory(val,
|
||||
option_bag)
|
||||
# Value must be valid for option
|
||||
opt.impl_validate(val,
|
||||
option_bag,
|
||||
check_error=True)
|
||||
await opt.impl_validate(val,
|
||||
option_bag,
|
||||
check_error=True)
|
||||
if 'warnings' in option_bag.config_bag.properties:
|
||||
# No error found so emit warnings
|
||||
opt.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
await opt.impl_validate(value,
|
||||
option_bag,
|
||||
check_error=False)
|
||||
|
||||
def _setvalue(self,
|
||||
option_bag,
|
||||
value,
|
||||
owner,
|
||||
commit=True):
|
||||
option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
self._p_.setvalue(option_bag.path,
|
||||
value,
|
||||
owner,
|
||||
option_bag.index,
|
||||
commit)
|
||||
async def _setvalue(self,
|
||||
option_bag,
|
||||
value,
|
||||
owner,
|
||||
commit=True):
|
||||
await option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
|
||||
await self._p_.setvalue(option_bag.path,
|
||||
value,
|
||||
owner,
|
||||
option_bag.index,
|
||||
commit)
|
||||
|
||||
def _get_modified_parent(self,
|
||||
option_bag: OptionBag) -> Optional[OptionBag]:
|
||||
async def _get_modified_parent(self,
|
||||
option_bag: OptionBag) -> Optional[OptionBag]:
|
||||
""" Search in differents parents a Config with a modified value
|
||||
If not found, return None
|
||||
For follower option, return the Config where leader is modified
|
||||
@ -361,13 +372,13 @@ class Values(object):
|
||||
# remove force_metaconfig_on_freeze only if option in metaconfig
|
||||
# hasn't force_metaconfig_on_freeze properties
|
||||
ori_properties = doption_bag.properties
|
||||
del doption_bag.properties
|
||||
if not self.force_to_metaconfig(doption_bag):
|
||||
doption_bag.properties = await doption_bag.config_bag.context.cfgimpl_get_settings().getproperties(doption_bag)
|
||||
if not await self.force_to_metaconfig(doption_bag):
|
||||
doption_bag.properties = ori_properties - {'force_metaconfig_on_freeze'}
|
||||
else:
|
||||
doption_bag.properties = ori_properties
|
||||
parent_owner = parent.cfgimpl_get_values().getowner(doption_bag,
|
||||
only_default=True)
|
||||
parent_owner = await parent.cfgimpl_get_values().getowner(doption_bag,
|
||||
only_default=True)
|
||||
if parent_owner != owners.default:
|
||||
return doption_bag
|
||||
|
||||
@ -377,17 +388,17 @@ class Values(object):
|
||||
#______________________________________________________________________
|
||||
# owner
|
||||
|
||||
def is_default_owner(self,
|
||||
option_bag,
|
||||
validate_meta=True):
|
||||
return self.getowner(option_bag,
|
||||
validate_meta=validate_meta,
|
||||
only_default=True) == owners.default
|
||||
async def is_default_owner(self,
|
||||
option_bag,
|
||||
validate_meta=True):
|
||||
return await self.getowner(option_bag,
|
||||
validate_meta=validate_meta,
|
||||
only_default=True) == owners.default
|
||||
|
||||
def getowner(self,
|
||||
option_bag,
|
||||
validate_meta=True,
|
||||
only_default=False):
|
||||
async def getowner(self,
|
||||
option_bag,
|
||||
validate_meta=True,
|
||||
only_default=False):
|
||||
"""
|
||||
retrieves the option's owner
|
||||
|
||||
@ -404,33 +415,33 @@ class Values(object):
|
||||
option_bag.option = opt
|
||||
option_bag.path = opt.impl_getpath()
|
||||
settings = context.cfgimpl_get_settings()
|
||||
settings.validate_properties(option_bag)
|
||||
await settings.validate_properties(option_bag)
|
||||
if 'frozen' in option_bag.properties and \
|
||||
'force_default_on_freeze' in option_bag.properties:
|
||||
return owners.default
|
||||
if only_default:
|
||||
if self._p_.hasvalue(option_bag.path,
|
||||
option_bag.index):
|
||||
if await self._p_.hasvalue(option_bag.path,
|
||||
option_bag.index):
|
||||
owner = 'not_default'
|
||||
else:
|
||||
owner = owners.default
|
||||
else:
|
||||
owner = self._p_.getowner(option_bag.path,
|
||||
owners.default,
|
||||
index=option_bag.index)
|
||||
owner = await self._p_.getowner(option_bag.path,
|
||||
owners.default,
|
||||
index=option_bag.index)
|
||||
if validate_meta is not False and (owner is owners.default or \
|
||||
'frozen' in option_bag.properties and 'force_metaconfig_on_freeze' in option_bag.properties):
|
||||
moption_bag = self._get_modified_parent(option_bag)
|
||||
moption_bag = await self._get_modified_parent(option_bag)
|
||||
if moption_bag is not None:
|
||||
owner = moption_bag.config_bag.context.cfgimpl_get_values().getowner(moption_bag,
|
||||
only_default=only_default)
|
||||
owner = await moption_bag.config_bag.context.cfgimpl_get_values().getowner(moption_bag,
|
||||
only_default=only_default)
|
||||
elif 'force_metaconfig_on_freeze' in option_bag.properties:
|
||||
return owners.default
|
||||
return owner
|
||||
|
||||
def setowner(self,
|
||||
owner,
|
||||
option_bag):
|
||||
async def setowner(self,
|
||||
owner,
|
||||
option_bag):
|
||||
"""
|
||||
sets a owner to an option
|
||||
|
||||
@ -444,103 +455,101 @@ class Values(object):
|
||||
if owner in forbidden_owners:
|
||||
raise ValueError(_('set owner "{0}" is forbidden').format(str(owner)))
|
||||
|
||||
if not self._p_.hasvalue(option_bag.path):
|
||||
if not await self._p_.hasvalue(option_bag.path):
|
||||
raise ConfigError(_('no value for {0} cannot change owner to {1}'
|
||||
'').format(option_bag.path, owner))
|
||||
option_bag.config_bag.context.cfgimpl_get_settings().validate_frozen(option_bag)
|
||||
self._p_.setowner(option_bag.path,
|
||||
await self._p_.setowner(option_bag.path,
|
||||
owner,
|
||||
index=option_bag.index)
|
||||
#______________________________________________________________________
|
||||
# reset
|
||||
|
||||
def reset(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
async def reset(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
|
||||
context = option_bag.config_bag.context
|
||||
hasvalue = self._p_.hasvalue(option_bag.path)
|
||||
hasvalue = await self._p_.hasvalue(option_bag.path)
|
||||
setting_properties = option_bag.config_bag.properties
|
||||
|
||||
if hasvalue and 'validator' in option_bag.config_bag.properties:
|
||||
fake_context = context._gen_fake_values()
|
||||
fake_context = await context._gen_fake_values()
|
||||
config_bag = option_bag.config_bag.copy()
|
||||
config_bag.remove_validation()
|
||||
config_bag.context = fake_context
|
||||
soption_bag = option_bag.copy()
|
||||
soption_bag.config_bag = config_bag
|
||||
fake_value = fake_context.cfgimpl_get_values()
|
||||
fake_value.reset(soption_bag)
|
||||
await fake_value.reset(soption_bag)
|
||||
soption_bag.config_bag.properties = option_bag.config_bag.properties
|
||||
value = fake_value.getdefaultvalue(soption_bag)
|
||||
fake_value.setvalue_validation(value,
|
||||
soption_bag)
|
||||
value = await fake_value.getdefaultvalue(soption_bag)
|
||||
await fake_value.setvalue_validation(value,
|
||||
soption_bag)
|
||||
opt = option_bag.option
|
||||
if opt.impl_is_leader():
|
||||
opt.impl_get_leadership().reset(self,
|
||||
option_bag,
|
||||
_commit=_commit)
|
||||
await opt.impl_get_leadership().reset(self,
|
||||
option_bag,
|
||||
_commit=_commit)
|
||||
if hasvalue:
|
||||
if 'force_store_value' in option_bag.config_bag.properties and 'force_store_value' in option_bag.properties:
|
||||
value = self.getdefaultvalue(option_bag)
|
||||
value = await self.getdefaultvalue(option_bag)
|
||||
|
||||
self._setvalue(option_bag,
|
||||
value,
|
||||
owners.forced,
|
||||
commit=_commit)
|
||||
await self._setvalue(option_bag,
|
||||
value,
|
||||
owners.forced,
|
||||
commit=_commit)
|
||||
else:
|
||||
# for leader only
|
||||
value = None
|
||||
self._p_.resetvalue(option_bag.path,
|
||||
_commit)
|
||||
context.cfgimpl_reset_cache(option_bag)
|
||||
await self._p_.resetvalue(option_bag.path,
|
||||
_commit)
|
||||
await context.cfgimpl_reset_cache(option_bag)
|
||||
if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader():
|
||||
if value is None:
|
||||
value = self.getdefaultvalue(option_bag)
|
||||
option_bag.option.impl_get_leadership().follower_force_store_value(self,
|
||||
value,
|
||||
option_bag,
|
||||
owners.forced,
|
||||
_commit=_commit)
|
||||
value = await self.getdefaultvalue(option_bag)
|
||||
await option_bag.option.impl_get_leadership().follower_force_store_value(self,
|
||||
value,
|
||||
option_bag,
|
||||
owners.forced,
|
||||
_commit=_commit)
|
||||
|
||||
def reset_follower(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
|
||||
if self._p_.hasvalue(option_bag.path, index=option_bag.index):
|
||||
async def reset_follower(self,
|
||||
option_bag,
|
||||
_commit=True):
|
||||
if await self._p_.hasvalue(option_bag.path, index=option_bag.index):
|
||||
context = option_bag.config_bag.context
|
||||
setting_properties = option_bag.config_bag.properties
|
||||
if 'validator' in setting_properties:
|
||||
fake_context = context._gen_fake_values()
|
||||
fake_context = await context._gen_fake_values()
|
||||
fake_value = fake_context.cfgimpl_get_values()
|
||||
config_bag = option_bag.config_bag.copy()
|
||||
config_bag.remove_validation()
|
||||
config_bag.context = fake_context
|
||||
soption_bag = option_bag.copy()
|
||||
soption_bag.config_bag = config_bag
|
||||
fake_value.reset_follower(soption_bag)
|
||||
value = fake_value.getdefaultvalue(soption_bag)
|
||||
fake_value.setvalue_validation(value,
|
||||
soption_bag)
|
||||
await fake_value.reset_follower(soption_bag)
|
||||
value = await fake_value.getdefaultvalue(soption_bag)
|
||||
await fake_value.setvalue_validation(value,
|
||||
soption_bag)
|
||||
if 'force_store_value' in setting_properties and 'force_store_value' in option_bag.properties:
|
||||
value = self.getdefaultvalue(option_bag)
|
||||
value = await self.getdefaultvalue(option_bag)
|
||||
|
||||
self._setvalue(option_bag,
|
||||
value,
|
||||
owners.forced,
|
||||
commit=_commit)
|
||||
await self._setvalue(option_bag,
|
||||
value,
|
||||
owners.forced,
|
||||
commit=_commit)
|
||||
else:
|
||||
self._p_.resetvalue_index(option_bag.path,
|
||||
option_bag.index,
|
||||
_commit)
|
||||
context.cfgimpl_reset_cache(option_bag)
|
||||
await self._p_.resetvalue_index(option_bag.path,
|
||||
option_bag.index,
|
||||
_commit)
|
||||
await context.cfgimpl_reset_cache(option_bag)
|
||||
|
||||
def reset_leadership(self,
|
||||
index,
|
||||
option_bag,
|
||||
subconfig):
|
||||
|
||||
current_value = self.get_cached_value(option_bag)
|
||||
async def reset_leadership(self,
|
||||
index,
|
||||
option_bag,
|
||||
subconfig):
|
||||
current_value = await self.get_cached_value(option_bag)
|
||||
length = len(current_value)
|
||||
if index >= length:
|
||||
raise IndexError(_('index {} is greater than the length {} '
|
||||
@ -548,48 +557,64 @@ class Values(object):
|
||||
length,
|
||||
option_bag.option.impl_get_display_name()))
|
||||
current_value.pop(index)
|
||||
subconfig.cfgimpl_get_description().pop(self,
|
||||
index,
|
||||
option_bag)
|
||||
self.setvalue(current_value,
|
||||
option_bag,
|
||||
_commit=True)
|
||||
await subconfig.cfgimpl_get_description().pop(self,
|
||||
index,
|
||||
option_bag)
|
||||
await self.setvalue(current_value,
|
||||
option_bag,
|
||||
_commit=True)
|
||||
|
||||
#______________________________________________________________________
|
||||
# information
|
||||
|
||||
def set_information(self, key, value, path=None):
|
||||
async def set_information(self,
|
||||
key,
|
||||
value,
|
||||
path=None):
|
||||
"""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(path, key, value)
|
||||
await self._p_.set_information(path,
|
||||
key,
|
||||
value)
|
||||
|
||||
def get_information(self, key, default=undefined, path=None):
|
||||
async def get_information(self,
|
||||
key,
|
||||
default=undefined,
|
||||
path=None):
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
"""
|
||||
return self._p_.get_information(path, key, default)
|
||||
return await self._p_.get_information(path,
|
||||
key,
|
||||
default)
|
||||
|
||||
def del_information(self, key, raises=True, path=None):
|
||||
self._p_.del_information(path, key, raises)
|
||||
async def del_information(self,
|
||||
key,
|
||||
raises=True,
|
||||
path=None):
|
||||
await self._p_.del_information(path,
|
||||
key,
|
||||
raises)
|
||||
|
||||
def list_information(self, path=None):
|
||||
return self._p_.list_information(path)
|
||||
async def list_information(self,
|
||||
path=None):
|
||||
return await self._p_.list_information(path)
|
||||
|
||||
#______________________________________________________________________
|
||||
# mandatory warnings
|
||||
def _mandatory_warnings(self,
|
||||
context,
|
||||
config_bag,
|
||||
description,
|
||||
currpath,
|
||||
subconfig,
|
||||
od_config_bag):
|
||||
async def _mandatory_warnings(self,
|
||||
context,
|
||||
config_bag,
|
||||
description,
|
||||
currpath,
|
||||
subconfig,
|
||||
od_config_bag):
|
||||
settings = context.cfgimpl_get_settings()
|
||||
for option in description.get_children(config_bag):
|
||||
for option in await description.get_children(config_bag):
|
||||
name = option.impl_getname()
|
||||
path = '.'.join(currpath + [name])
|
||||
|
||||
@ -600,16 +625,19 @@ class Values(object):
|
||||
path,
|
||||
None,
|
||||
od_config_bag)
|
||||
subsubconfig = subconfig.get_subconfig(option_bag)
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
|
||||
subsubconfig = await subconfig.get_subconfig(option_bag)
|
||||
except PropertiesOptionError as err:
|
||||
pass
|
||||
else:
|
||||
yield from self._mandatory_warnings(context,
|
||||
config_bag,
|
||||
option,
|
||||
currpath + [name],
|
||||
subsubconfig,
|
||||
od_config_bag)
|
||||
async for option in self._mandatory_warnings(context,
|
||||
config_bag,
|
||||
option,
|
||||
currpath + [name],
|
||||
subsubconfig,
|
||||
od_config_bag):
|
||||
yield option
|
||||
elif not option.impl_is_symlinkoption():
|
||||
# don't verifying symlink
|
||||
try:
|
||||
@ -619,9 +647,10 @@ class Values(object):
|
||||
path,
|
||||
None,
|
||||
config_bag)
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
if 'mandatory' in option_bag.properties or 'empty' in option_bag.properties:
|
||||
subconfig.getattr(name,
|
||||
option_bag)
|
||||
await subconfig.getattr(name,
|
||||
option_bag)
|
||||
else:
|
||||
for index in range(subconfig.cfgimpl_get_length()):
|
||||
option_bag = OptionBag()
|
||||
@ -629,17 +658,18 @@ class Values(object):
|
||||
path,
|
||||
index,
|
||||
config_bag)
|
||||
option_bag.properties = await settings.getproperties(option_bag)
|
||||
if 'mandatory' in option_bag.properties or 'empty' in option_bag.properties:
|
||||
subconfig.getattr(name,
|
||||
option_bag)
|
||||
await subconfig.getattr(name,
|
||||
option_bag)
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype in (['mandatory'], ['empty']):
|
||||
yield path
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
def mandatory_warnings(self,
|
||||
config_bag):
|
||||
async def mandatory_warnings(self,
|
||||
config_bag):
|
||||
"""convenience function to trace Options that are mandatory and
|
||||
where no value has been set
|
||||
|
||||
@ -650,33 +680,36 @@ class Values(object):
|
||||
od_setting_properties = config_bag.properties - {'mandatory', 'empty'}
|
||||
setting_properties = set(config_bag.properties) - {'warnings'}
|
||||
setting_properties.update(['mandatory', 'empty'])
|
||||
config_bag = ConfigBag(context=config_bag.context)
|
||||
config_bag.properties = frozenset(setting_properties)
|
||||
config_bag = ConfigBag(context=config_bag.context,
|
||||
properties=frozenset(setting_properties),
|
||||
permissives=config_bag.permissives)
|
||||
config_bag.set_permissive()
|
||||
od_config_bag = ConfigBag(context=config_bag.context)
|
||||
od_config_bag.properties = frozenset(od_setting_properties)
|
||||
od_config_bag = ConfigBag(context=config_bag.context,
|
||||
properties=frozenset(od_setting_properties),
|
||||
permissives=config_bag.permissives)
|
||||
od_config_bag.set_permissive()
|
||||
|
||||
descr = context.cfgimpl_get_description()
|
||||
return self._mandatory_warnings(context,
|
||||
config_bag,
|
||||
descr,
|
||||
[],
|
||||
context,
|
||||
od_config_bag)
|
||||
async for option in self._mandatory_warnings(context,
|
||||
config_bag,
|
||||
descr,
|
||||
[],
|
||||
context,
|
||||
od_config_bag):
|
||||
yield option
|
||||
|
||||
#____________________________________________________________
|
||||
# default owner methods
|
||||
def set_context_owner(self,
|
||||
owner):
|
||||
async def set_context_owner(self,
|
||||
owner):
|
||||
":param owner: sets the default value for owner at the Config level"
|
||||
if owner in forbidden_owners:
|
||||
raise ValueError(_('set owner "{0}" is forbidden').format(str(owner)))
|
||||
|
||||
self._p_.setowner(None,
|
||||
owner,
|
||||
index=None)
|
||||
await self._p_.setowner(None,
|
||||
owner,
|
||||
index=None)
|
||||
|
||||
def get_context_owner(self):
|
||||
return self._p_.getowner(None,
|
||||
None)
|
||||
async def get_context_owner(self):
|
||||
return await self._p_.getowner(None,
|
||||
None)
|
||||
|
Reference in New Issue
Block a user