add some tests for dynoptiondescription + correction
This commit is contained in:
@ -24,7 +24,6 @@ from typing import Any, Optional, Union, Callable, Dict, List
|
||||
from .error import PropertiesOptionError, ConfigError, SlaveError
|
||||
from .i18n import _
|
||||
from .setting import undefined, ConfigBag, OptionBag, Undefined
|
||||
from .option.symlinkoption import DynSymLinkOption
|
||||
from .storage import get_default_values_storages, get_default_settings_storages
|
||||
from .function import ParamValue, ParamContext, ParamIndex, ParamOption, Params
|
||||
# ____________________________________________________________
|
||||
@ -48,13 +47,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||
return context.duplicate(force_values=get_default_values_storages(),
|
||||
force_settings=get_default_settings_storages())
|
||||
opt = callbk.option
|
||||
if opt.issubdyn():
|
||||
opt = DynSymLinkOption(opt,
|
||||
option._rootpath,
|
||||
option.impl_getsuffix())
|
||||
path = opt.impl_getpath(context)
|
||||
else:
|
||||
path = context.cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
path = opt.impl_getpath(context)
|
||||
if index is not None and opt.impl_is_master_slaves() and \
|
||||
opt.impl_get_master_slaves().in_same_group(option):
|
||||
if opt == option:
|
||||
|
@ -123,7 +123,8 @@ class SubConfig(object):
|
||||
for woption in option_bag.option._get_dependencies(self):
|
||||
option = woption()
|
||||
if option.impl_is_dynoptiondescription():
|
||||
for doption in option.get_syndynoptiondescriptions(option_bag):
|
||||
for doption in option.get_syndynoptiondescriptions(option_bag,
|
||||
remove_none=True):
|
||||
doption_path = doption.impl_getpath(self)
|
||||
doption_bag = OptionBag()
|
||||
doption_bag.set_option(doption,
|
||||
|
@ -3,7 +3,8 @@ from .dynoptiondescription import DynOptionDescription
|
||||
from .syndynoptiondescription import SynDynOptionDescription
|
||||
from .masterslave import MasterSlaves
|
||||
from .baseoption import submulti
|
||||
from .symlinkoption import SymLinkOption, DynSymLinkOption
|
||||
from .symlinkoption import SymLinkOption
|
||||
from .dynsymlinkoption import DynSymLinkOption
|
||||
from .option import Option, RegexpOption
|
||||
from .choiceoption import ChoiceOption
|
||||
from .booloption import BoolOption
|
||||
|
@ -28,6 +28,7 @@ from ..i18n import _
|
||||
from ..setting import undefined
|
||||
from ..error import ConfigError, display_list
|
||||
from ..function import Params, ParamContext, ParamOption, ParamIndex
|
||||
from .dynsymlinkoption import DynSymLinkOption
|
||||
|
||||
STATIC_TUPLE = frozenset()
|
||||
|
||||
@ -450,6 +451,13 @@ class BaseOption(Base):
|
||||
class OnlyOption(BaseOption):
|
||||
__slots__ = tuple()
|
||||
|
||||
def impl_get_dynoption(self,
|
||||
rootpath,
|
||||
suffix):
|
||||
return DynSymLinkOption(self,
|
||||
rootpath,
|
||||
suffix)
|
||||
|
||||
|
||||
def validate_requires_arg(new_option,
|
||||
multi,
|
||||
|
@ -71,8 +71,9 @@ class DynOptionDescription(OptionDescription):
|
||||
raise ConfigError(_('callback is mandatory for the dynoptiondescription "{}"'
|
||||
'').format(self.impl_get_display_name()))
|
||||
|
||||
def _impl_get_suffixes(self,
|
||||
option_bag):
|
||||
def impl_get_suffixes(self,
|
||||
option_bag,
|
||||
remove_none=False):
|
||||
callback, callback_params = self.impl_get_callback()
|
||||
values = carry_out_calculation(self,
|
||||
option_bag.config_bag.context,
|
||||
@ -83,18 +84,30 @@ class DynOptionDescription(OptionDescription):
|
||||
if not isinstance(values, list):
|
||||
raise ValueError(_('DynOptionDescription callback for option "{}", is not a list ({})'
|
||||
'').format(self.impl_get_display_name(), values))
|
||||
if len(values) > len(set(values)):
|
||||
raise ValueError(_('DynOptionDescription callback return not unique value'))
|
||||
values_ = []
|
||||
for val in values:
|
||||
if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None:
|
||||
raise ValueError(_('invalid suffix "{}" for option "{}"'
|
||||
'').format(val,
|
||||
self.impl_get_display_name()))
|
||||
return values
|
||||
if not remove_none or val is not None:
|
||||
raise ValueError(_('invalid suffix "{}" for option "{}"'
|
||||
'').format(val,
|
||||
self.impl_get_display_name()))
|
||||
else:
|
||||
values_.append(val)
|
||||
values = values_
|
||||
if len(values) > len(set(values)):
|
||||
extra_values = values.copy()
|
||||
for val in set(values):
|
||||
extra_values.remove(val)
|
||||
raise ValueError(_('DynOptionDescription callback return a list with multiple value '
|
||||
'"{}"''').format(extra_values))
|
||||
return values_
|
||||
|
||||
def get_syndynoptiondescriptions(self, option_bag):
|
||||
def get_syndynoptiondescriptions(self,
|
||||
option_bag,
|
||||
remove_none=False):
|
||||
subpath = self.impl_getpath(option_bag.config_bag.context).rsplit('.', 1)[0]
|
||||
for suffix in self._impl_get_suffixes(option_bag):
|
||||
for suffix in self.impl_get_suffixes(option_bag,
|
||||
remove_none=remove_none):
|
||||
yield SynDynOptionDescription(self,
|
||||
subpath,
|
||||
suffix)
|
||||
|
83
tiramisu/option/dynsymlinkoption.py
Normal file
83
tiramisu/option/dynsymlinkoption.py
Normal file
@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# The original `Config` design model is unproudly borrowed from
|
||||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
from ..setting import undefined, OptionBag
|
||||
|
||||
|
||||
class DynSymLinkOption(object):
|
||||
__slots__ = ('_rootpath',
|
||||
'_opt',
|
||||
'_suffix')
|
||||
|
||||
def __init__(self,
|
||||
opt,
|
||||
rootpath,
|
||||
suffix):
|
||||
self._opt = opt
|
||||
self._rootpath = rootpath
|
||||
self._suffix = suffix
|
||||
|
||||
def __getattr__(self,
|
||||
name):
|
||||
return getattr(self._opt, name)
|
||||
|
||||
def __eq__(self, left):
|
||||
if not isinstance(left, DynSymLinkOption):
|
||||
return False
|
||||
return self._opt == left._opt and \
|
||||
self._rootpath == left._rootpath and \
|
||||
self._suffix == left._suffix
|
||||
|
||||
def impl_getname(self):
|
||||
return self._opt.impl_getname() + self._suffix
|
||||
|
||||
def impl_get_display_name(self):
|
||||
return self._opt.impl_get_display_name(dyn_name=self.impl_getname())
|
||||
|
||||
def impl_getopt(self):
|
||||
return self._opt
|
||||
|
||||
def impl_getsuffix(self):
|
||||
return self._suffix
|
||||
|
||||
def impl_getpath(self,
|
||||
context):
|
||||
return self._rootpath + '.' + self.impl_getname()
|
||||
|
||||
def impl_validate(self,
|
||||
value,
|
||||
option_bag,
|
||||
context=undefined,
|
||||
check_error=True):
|
||||
context = option_bag.config_bag.context
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(self._opt,
|
||||
self.impl_getpath(context),
|
||||
option_bag.index,
|
||||
option_bag.config_bag)
|
||||
soption_bag.ori_option = option_bag.option
|
||||
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
|
||||
self._opt.impl_validate(value,
|
||||
soption_bag,
|
||||
context=context,
|
||||
check_error=check_error)
|
||||
|
||||
def impl_is_dynsymlinkoption(self):
|
||||
return True
|
@ -23,7 +23,6 @@ import warnings
|
||||
import weakref
|
||||
|
||||
from .baseoption import OnlyOption, submulti, STATIC_TUPLE
|
||||
from .symlinkoption import DynSymLinkOption
|
||||
from ..i18n import _
|
||||
from ..setting import log, undefined, debug, OptionBag
|
||||
from ..autolib import carry_out_calculation
|
||||
@ -457,7 +456,7 @@ class Option(OnlyOption):
|
||||
if descr._cache_consistencies is None:
|
||||
return
|
||||
# get consistencies for this option
|
||||
if isinstance(option_bag.option, DynSymLinkOption):
|
||||
if option_bag.option.impl_is_dynsymlinkoption():
|
||||
consistencies = descr._cache_consistencies.get(option_bag.option.impl_getopt())
|
||||
else:
|
||||
consistencies = descr._cache_consistencies.get(option_bag.option)
|
||||
@ -475,12 +474,11 @@ class Option(OnlyOption):
|
||||
if (warnings_only and not check_error) or (not warnings_only and check_error):
|
||||
transitive = params.get('transitive', True)
|
||||
#all_cons_opts[0] is the option where func is set
|
||||
if isinstance(option_bag.ori_option, DynSymLinkOption):
|
||||
if option_bag.ori_option.impl_is_dynsymlinkoption():
|
||||
opts = []
|
||||
for opt in all_cons_opts:
|
||||
opts.append(DynSymLinkOption(opt(),
|
||||
option_bag.ori_option._rootpath,
|
||||
option_bag.ori_option._suffix))
|
||||
opts.append(opt().impl_get_dynoption(option_bag.ori_option._rootpath,
|
||||
option_bag.ori_option._suffix))
|
||||
wopt = opts[0]
|
||||
else:
|
||||
opts = all_cons_opts
|
||||
|
@ -24,7 +24,7 @@ from copy import copy
|
||||
from ..i18n import _
|
||||
from ..setting import ConfigBag, OptionBag, groups, undefined, owners
|
||||
from .baseoption import BaseOption, OnlyOption
|
||||
from .option import ALLOWED_CONST_LIST, DynSymLinkOption
|
||||
from .option import ALLOWED_CONST_LIST
|
||||
from .syndynoptiondescription import SynDynOptionDescription
|
||||
from ..error import ConfigError, ConflictError
|
||||
|
||||
@ -234,12 +234,11 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
ori_index = len(rootpath) + 1
|
||||
subpaths = [rootpath] + option.impl_getpath(
|
||||
option_bag.config_bag.context)[ori_index:].split('.')[:-1]
|
||||
for suffix in dynopt._impl_get_suffixes(option_bag):
|
||||
for suffix in dynopt.impl_get_suffixes(option_bag):
|
||||
subpath = '.'.join([subp + suffix for subp in subpaths])
|
||||
if isinstance(option, OnlyOption):
|
||||
yield DynSymLinkOption(option,
|
||||
subpath,
|
||||
suffix)
|
||||
yield option.impl_get_dynoption(subpath,
|
||||
suffix)
|
||||
else:
|
||||
yield SynDynOptionDescription(option,
|
||||
subpath,
|
||||
@ -333,7 +332,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
subpath,
|
||||
None,
|
||||
config_bag)
|
||||
for suffix in child._impl_get_suffixes(option_bag):
|
||||
for suffix in child.impl_get_suffixes(option_bag):
|
||||
yield SynDynOptionDescription(child,
|
||||
subpath,
|
||||
suffix)
|
||||
@ -360,7 +359,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
subconfig.cfgimpl_get_path(),
|
||||
None,
|
||||
config_bag)
|
||||
for value in child._impl_get_suffixes(option_bag):
|
||||
for value in child.impl_get_suffixes(option_bag):
|
||||
if name == cname + value:
|
||||
return SynDynOptionDescription(child,
|
||||
subconfig.cfgimpl_get_path(),
|
||||
@ -375,9 +374,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
subpath,
|
||||
suffix)
|
||||
else:
|
||||
return DynSymLinkOption(child,
|
||||
subpath,
|
||||
suffix)
|
||||
return child.impl_get_dynoption(subpath,
|
||||
suffix)
|
||||
|
||||
|
||||
class OptionDescription(OptionDescriptionWalk):
|
||||
|
@ -20,7 +20,6 @@
|
||||
# ____________________________________________________________
|
||||
from .baseoption import OnlyOption
|
||||
from ..i18n import _
|
||||
from ..setting import undefined, OptionBag
|
||||
|
||||
|
||||
class SymLinkOption(OnlyOption):
|
||||
@ -60,65 +59,3 @@ class SymLinkOption(OnlyOption):
|
||||
|
||||
def get_consistencies(self):
|
||||
return ()
|
||||
|
||||
|
||||
class DynSymLinkOption(object):
|
||||
__slots__ = ('_rootpath',
|
||||
'_opt',
|
||||
'_suffix')
|
||||
|
||||
def __init__(self,
|
||||
opt,
|
||||
rootpath,
|
||||
suffix):
|
||||
self._opt = opt
|
||||
self._rootpath = rootpath
|
||||
self._suffix = suffix
|
||||
|
||||
def __getattr__(self,
|
||||
name):
|
||||
return getattr(self._opt, name)
|
||||
|
||||
def __eq__(self, left):
|
||||
if not isinstance(left, DynSymLinkOption):
|
||||
return False
|
||||
return self._opt == left._opt and \
|
||||
self._rootpath == left._rootpath and \
|
||||
self._suffix == left._suffix
|
||||
|
||||
def impl_getname(self):
|
||||
return self._opt.impl_getname() + self._suffix
|
||||
|
||||
def impl_get_display_name(self):
|
||||
return self._opt.impl_get_display_name(dyn_name=self.impl_getname())
|
||||
|
||||
def impl_getopt(self):
|
||||
return self._opt
|
||||
|
||||
def impl_getsuffix(self):
|
||||
return self._suffix
|
||||
|
||||
def impl_getpath(self,
|
||||
context):
|
||||
return self._rootpath + '.' + self.impl_getname()
|
||||
|
||||
def impl_validate(self,
|
||||
value,
|
||||
option_bag,
|
||||
context=undefined,
|
||||
check_error=True):
|
||||
context = option_bag.config_bag.context
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(self._opt,
|
||||
self.impl_getpath(context),
|
||||
option_bag.index,
|
||||
option_bag.config_bag)
|
||||
soption_bag.ori_option = option_bag.option
|
||||
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
|
||||
self._opt.impl_validate(value,
|
||||
soption_bag,
|
||||
context=context,
|
||||
check_error=check_error)
|
||||
|
||||
def impl_is_dynsymlinkoption(self):
|
||||
return True
|
||||
|
@ -20,7 +20,6 @@
|
||||
# ____________________________________________________________
|
||||
from ..i18n import _
|
||||
from ..setting import groups, undefined
|
||||
from .symlinkoption import DynSymLinkOption
|
||||
|
||||
|
||||
class SynDynOptionDescription(object):
|
||||
@ -81,16 +80,20 @@ class SynDynOptionDescription(object):
|
||||
|
||||
def getmaster(self):
|
||||
master = self._opt.getmaster()
|
||||
return DynSymLinkOption(master,
|
||||
self.impl_getpath(None),
|
||||
self._suffix)
|
||||
return master.impl_get_dynoption(self.impl_getpath(None),
|
||||
self._suffix)
|
||||
|
||||
def getslaves(self):
|
||||
subpath = self.impl_getpath(None)
|
||||
for slave in self._opt.getslaves():
|
||||
yield DynSymLinkOption(slave,
|
||||
subpath,
|
||||
self._suffix)
|
||||
yield slave.impl_get_dynoption(subpath,
|
||||
self._suffix)
|
||||
|
||||
def impl_get_display_name(self):
|
||||
return self._opt.impl_get_display_name() + self._suffix
|
||||
|
||||
def impl_getdoc(self):
|
||||
return self._opt.impl_getdoc() + self._suffix
|
||||
|
||||
def reset_cache(self,
|
||||
path,
|
||||
|
@ -484,8 +484,11 @@ class Settings(object):
|
||||
exps, action, inverse, transitive, same_action, operator = require
|
||||
breaked = False
|
||||
for option, expected in exps:
|
||||
if option.issubdyn():
|
||||
option = option.impl_get_dynoption(option_bag.option._rootpath,
|
||||
option_bag.option.impl_getsuffix())
|
||||
reqpath = option.impl_getpath(context)
|
||||
#FIXME c'est un peu tard !
|
||||
#FIXME too later!
|
||||
if reqpath.startswith(option_bag.path + '.'):
|
||||
raise RequirementError(_("malformed requirements "
|
||||
"imbrication detected for option:"
|
||||
|
Reference in New Issue
Block a user