simplify tiramisu/option/baseoption.py
This commit is contained in:
parent
8b3da4d37b
commit
92b469bd43
|
@ -25,7 +25,6 @@ def test_option_valid_name():
|
||||||
raises(ValueError, 'IntOption(1, "")')
|
raises(ValueError, 'IntOption(1, "")')
|
||||||
raises(ValueError, 'IntOption("1test", "")')
|
raises(ValueError, 'IntOption("1test", "")')
|
||||||
IntOption("test1", "")
|
IntOption("test1", "")
|
||||||
raises(ValueError, 'IntOption("impl_test", "")')
|
|
||||||
raises(ValueError, 'IntOption("_test", "")')
|
raises(ValueError, 'IntOption("_test", "")')
|
||||||
raises(ValueError, 'IntOption(" ", "")')
|
raises(ValueError, 'IntOption(" ", "")')
|
||||||
|
|
||||||
|
|
|
@ -264,15 +264,15 @@ def test_param_option():
|
||||||
|
|
||||||
|
|
||||||
def test_callback_invalid():
|
def test_callback_invalid():
|
||||||
raises(ValueError, 'val1 = StrOption("val1", "", callback="string")')
|
raises(AssertionError, 'val1 = StrOption("val1", "", callback="string")')
|
||||||
raises(ValueError, 'val1 = StrOption("val1", "", callback=return_val, callback_params="string")')
|
raises(AssertionError, 'val1 = StrOption("val1", "", callback=return_val, callback_params="string")')
|
||||||
val1 = StrOption('val1', "", 'val')
|
val1 = StrOption('val1', "", 'val')
|
||||||
val1
|
val1
|
||||||
raises(ValueError, "StrOption('val2', '', callback=return_value, callback_params={'': 'string'})")
|
raises(AssertionError, "StrOption('val2', '', callback=return_value, callback_params={'': 'string'})")
|
||||||
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': (('string', False),)})")
|
raises(AssertionError, "StrOption('val4', '', callback=return_value, callback_params={'value': (('string', False),)})")
|
||||||
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, 'string'),)})")
|
raises(AssertionError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, 'string'),)})")
|
||||||
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, False, 'unknown'),)})")
|
raises(AssertionError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, False, 'unknown'),)})")
|
||||||
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1,),)})")
|
raises(AssertionError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1,),)})")
|
||||||
|
|
||||||
|
|
||||||
def test_callback_with_context():
|
def test_callback_with_context():
|
||||||
|
|
|
@ -55,9 +55,8 @@ def test_optname_shall_not_start_with_numbers():
|
||||||
|
|
||||||
|
|
||||||
def test_option_has_an_api_name():
|
def test_option_has_an_api_name():
|
||||||
raises(ValueError, "BoolOption('cfgimpl_get_settings', 'dummy', default=False)")
|
b = BoolOption('impl_has_dependency', 'dummy', default=True)
|
||||||
raises(ValueError, "BoolOption('impl_getdoc', 'dummy', default=False)")
|
descr = OptionDescription('tiramisu', '', [b])
|
||||||
raises(ValueError, "BoolOption('_unvalid', 'dummy', default=False)")
|
api = Config(descr)
|
||||||
raises(ValueError, "BoolOption('6unvalid', 'dummy', default=False)")
|
assert api.option('impl_has_dependency').value.get() is True
|
||||||
BoolOption('unvalid6', 'dummy', default=False)
|
assert b.impl_has_dependency() is False
|
||||||
BoolOption('unvalid_', 'dummy', default=False)
|
|
||||||
|
|
|
@ -121,42 +121,6 @@ def test_slots_option_readonly():
|
||||||
raises(AttributeError, "q._requires = 'q'")
|
raises(AttributeError, "q._requires = 'q'")
|
||||||
|
|
||||||
|
|
||||||
def test_slots_option_readonly_name():
|
|
||||||
a = ChoiceOption('a', '', ('a',))
|
|
||||||
b = BoolOption('b', '')
|
|
||||||
c = IntOption('c', '')
|
|
||||||
d = FloatOption('d', '')
|
|
||||||
e = StrOption('e', '')
|
|
||||||
f = SymLinkOption('f', c)
|
|
||||||
g = UnicodeOption('g', '')
|
|
||||||
h = IPOption('h', '')
|
|
||||||
i = PortOption('i', '')
|
|
||||||
j = NetworkOption('j', '')
|
|
||||||
k = NetmaskOption('k', '')
|
|
||||||
l = DomainnameOption('l', '')
|
|
||||||
o = DomainnameOption('o', '')
|
|
||||||
p = DomainnameOption('p', '')
|
|
||||||
q = DomainnameOption('q', '')
|
|
||||||
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l, o, p, q])
|
|
||||||
m
|
|
||||||
raises(AttributeError, "a._name = 'a'")
|
|
||||||
raises(AttributeError, "b._name = 'b'")
|
|
||||||
raises(AttributeError, "c._name = 'c'")
|
|
||||||
raises(AttributeError, "d._name = 'd'")
|
|
||||||
raises(AttributeError, "e._name = 'e'")
|
|
||||||
raises(AttributeError, "f._name = 'f'")
|
|
||||||
raises(AttributeError, "g._name = 'g'")
|
|
||||||
raises(AttributeError, "h._name = 'h'")
|
|
||||||
raises(AttributeError, "i._name = 'i'")
|
|
||||||
raises(AttributeError, "j._name = 'j'")
|
|
||||||
raises(AttributeError, "k._name = 'k'")
|
|
||||||
raises(AttributeError, "l._name = 'l'")
|
|
||||||
raises(AttributeError, "m._name = 'm'")
|
|
||||||
raises(AttributeError, "o._name = 'o'")
|
|
||||||
raises(AttributeError, "p._name = 'p'")
|
|
||||||
raises(AttributeError, "q._name = 'q'")
|
|
||||||
|
|
||||||
|
|
||||||
#def test_slots_description():
|
#def test_slots_description():
|
||||||
# # __slots__ for OptionDescription should be complete for __getattr__
|
# # __slots__ for OptionDescription should be complete for __getattr__
|
||||||
# slots = set()
|
# slots = set()
|
||||||
|
|
|
@ -113,7 +113,7 @@ class SubConfig(object):
|
||||||
if option_bag.path in resetted_opts:
|
if option_bag.path in resetted_opts:
|
||||||
return
|
return
|
||||||
resetted_opts.append(option_bag.path)
|
resetted_opts.append(option_bag.path)
|
||||||
for woption in option_bag.option._get_dependencies(self):
|
for woption in option_bag.option._get_dependencies(self.cfgimpl_get_description()):
|
||||||
option = woption()
|
option = woption()
|
||||||
if option.impl_is_dynoptiondescription():
|
if option.impl_is_dynoptiondescription():
|
||||||
subpath = option.impl_getpath().rsplit('.', 1)[0]
|
subpath = option.impl_getpath().rsplit('.', 1)[0]
|
||||||
|
|
|
@ -23,6 +23,8 @@ def display_list(lst, separator='and', add_quote=False):
|
||||||
separator = _('and')
|
separator = _('and')
|
||||||
elif separator == 'or':
|
elif separator == 'or':
|
||||||
separator = _('or')
|
separator = _('or')
|
||||||
|
if isinstance(lst, tuple) or isinstance(lst, frozenset):
|
||||||
|
lst = list(lst)
|
||||||
if len(lst) == 1:
|
if len(lst) == 1:
|
||||||
ret = lst[0]
|
ret = lst[0]
|
||||||
if not isinstance(ret, str):
|
if not isinstance(ret, str):
|
||||||
|
@ -31,8 +33,6 @@ def display_list(lst, separator='and', add_quote=False):
|
||||||
ret = '"{}"'.format(ret)
|
ret = '"{}"'.format(ret)
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
if isinstance(lst, tuple):
|
|
||||||
lst = list(lst)
|
|
||||||
lst.sort()
|
lst.sort()
|
||||||
lst_ = []
|
lst_ = []
|
||||||
for l in lst[:-1]:
|
for l in lst[:-1]:
|
||||||
|
|
|
@ -20,13 +20,15 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import re
|
import re
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
|
from typing import FrozenSet, Callable, Tuple, Set, Optional, Union, Any, List
|
||||||
import weakref
|
import weakref
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined
|
from ..setting import undefined, Settings
|
||||||
|
from ..value import Values
|
||||||
from ..error import ConfigError, display_list
|
from ..error import ConfigError, display_list
|
||||||
from ..function import Params, ParamContext, ParamOption, ParamIndex
|
from ..function import Params, ParamContext, ParamOption, ParamIndex
|
||||||
|
|
||||||
|
@ -38,18 +40,14 @@ NAME_REGEXP = re.compile(r'^[a-zA-Z][a-zA-Z\d_-]*$')
|
||||||
|
|
||||||
|
|
||||||
def valid_name(name):
|
def valid_name(name):
|
||||||
"""an option's name is a str and does not start with 'impl' or 'cfgimpl'
|
|
||||||
and name is not a function name"""
|
|
||||||
if not isinstance(name, str):
|
if not isinstance(name, str):
|
||||||
return False
|
return False
|
||||||
return re.match(NAME_REGEXP, name) is not None and \
|
return re.match(NAME_REGEXP, name) is not None
|
||||||
not name.startswith('impl_') and \
|
|
||||||
not name.startswith('cfgimpl_')
|
|
||||||
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
#
|
#
|
||||||
class Base(object):
|
class Base:
|
||||||
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name',
|
__slots__ = ('_name',
|
||||||
|
@ -70,13 +68,13 @@ class Base(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name: str,
|
||||||
doc,
|
doc: str,
|
||||||
requires=None,
|
requires=None,
|
||||||
properties=None,
|
properties=None,
|
||||||
is_multi=False):
|
is_multi: bool=False) -> None:
|
||||||
if not valid_name(name):
|
if not valid_name(name):
|
||||||
raise ValueError(_('invalid name: "{0}" for option').format(name))
|
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||||
if requires is not None:
|
if requires is not None:
|
||||||
calc_properties, requires = validate_requires_arg(self,
|
calc_properties, requires = validate_requires_arg(self,
|
||||||
is_multi,
|
is_multi,
|
||||||
|
@ -90,12 +88,16 @@ class Base(object):
|
||||||
if isinstance(properties, tuple):
|
if isinstance(properties, tuple):
|
||||||
properties = frozenset(properties)
|
properties = frozenset(properties)
|
||||||
if is_multi and 'empty' not in properties:
|
if is_multi and 'empty' not in properties:
|
||||||
|
# if option is a multi, it cannot be "empty" (None not allowed in the list)
|
||||||
|
# "empty" is removed for slave's option
|
||||||
properties = properties | {'empty'}
|
properties = properties | {'empty'}
|
||||||
if not isinstance(properties, frozenset):
|
if not isinstance(properties, frozenset):
|
||||||
raise TypeError(_('invalid properties type {0} for {1},'
|
raise TypeError(_('invalid properties type {0} for {1},'
|
||||||
' must be a frozenset').format(type(properties),
|
' must be a frozenset').format(type(properties),
|
||||||
name))
|
name))
|
||||||
self.validate_properties(name, calc_properties, properties)
|
self.validate_properties(name,
|
||||||
|
calc_properties,
|
||||||
|
properties)
|
||||||
_setattr = object.__setattr__
|
_setattr = object.__setattr__
|
||||||
_setattr(self, '_name', name)
|
_setattr(self, '_name', name)
|
||||||
_setattr(self, '_informations', {'doc': doc})
|
_setattr(self, '_informations', {'doc': doc})
|
||||||
|
@ -106,15 +108,18 @@ class Base(object):
|
||||||
if properties:
|
if properties:
|
||||||
_setattr(self, '_properties', properties)
|
_setattr(self, '_properties', properties)
|
||||||
|
|
||||||
def validate_properties(self, name, calc_properties, properties):
|
def validate_properties(self,
|
||||||
|
name: str,
|
||||||
|
calc_properties: FrozenSet[str],
|
||||||
|
properties: FrozenSet[str]) -> None:
|
||||||
set_forbidden_properties = calc_properties & properties
|
set_forbidden_properties = calc_properties & properties
|
||||||
if set_forbidden_properties != frozenset():
|
if set_forbidden_properties != frozenset():
|
||||||
raise ValueError(_('conflict: properties already set in requirement {0} for {1}'
|
raise ValueError(_('conflict: properties already set in requirement {0} for {1}'
|
||||||
'').format(display_list(list(set_forbidden_properties)),
|
'').format(display_list(set_forbidden_properties),
|
||||||
name))
|
name))
|
||||||
|
|
||||||
def _get_function_args(self,
|
def _get_function_args(self,
|
||||||
function):
|
function: Callable) -> Tuple[Set[str], Set[str], bool, bool]:
|
||||||
args = set()
|
args = set()
|
||||||
kwargs = set()
|
kwargs = set()
|
||||||
positional = False
|
positional = False
|
||||||
|
@ -131,8 +136,8 @@ class Base(object):
|
||||||
return args, kwargs, positional, keyword
|
return args, kwargs, positional, keyword
|
||||||
|
|
||||||
def _get_parameters_args(self,
|
def _get_parameters_args(self,
|
||||||
calculator_params,
|
calculator_params: Optional[Params],
|
||||||
add_value):
|
add_value: bool) -> Tuple[Set[str], Set[str]]:
|
||||||
args = set()
|
args = set()
|
||||||
kwargs = set()
|
kwargs = set()
|
||||||
# add value as first argument
|
# add value as first argument
|
||||||
|
@ -149,18 +154,17 @@ class Base(object):
|
||||||
return args, kwargs
|
return args, kwargs
|
||||||
|
|
||||||
def _build_calculator_params(self,
|
def _build_calculator_params(self,
|
||||||
calculator,
|
calculator: Callable,
|
||||||
calculator_params,
|
calculator_params: Optional[Params],
|
||||||
type_,
|
type_: str,
|
||||||
add_value=False):
|
add_value: bool=False) -> Union[None, Params]:
|
||||||
"""
|
"""
|
||||||
:add_value: add value as first argument for validator
|
:add_value: add value as first argument for validator
|
||||||
"""
|
"""
|
||||||
if not isinstance(calculator, FunctionType):
|
assert isinstance(calculator, FunctionType), _('{0} must be a function').format(type_)
|
||||||
raise ValueError(_('{0} must be a function').format(type_))
|
|
||||||
if calculator_params is not None:
|
if calculator_params is not None:
|
||||||
if not isinstance(calculator_params, Params):
|
assert isinstance(calculator_params, Params), _('{0}_params must be a params'
|
||||||
raise ValueError(_('{0}_params must be a params').format(type_))
|
'').format(type_)
|
||||||
for param in chain(calculator_params.args, calculator_params.kwargs.values()):
|
for param in chain(calculator_params.args, calculator_params.kwargs.values()):
|
||||||
if isinstance(param, ParamContext):
|
if isinstance(param, ParamContext):
|
||||||
self._has_calc_context = True
|
self._has_calc_context = True
|
||||||
|
@ -229,34 +233,28 @@ class Base(object):
|
||||||
return calculator_params
|
return calculator_params
|
||||||
|
|
||||||
def impl_has_dependency(self,
|
def impl_has_dependency(self,
|
||||||
self_is_dep=True):
|
self_is_dep: bool=True) -> bool:
|
||||||
if self_is_dep is True:
|
if self_is_dep is True:
|
||||||
#if self.impl_is_master_slaves():
|
|
||||||
# return True
|
|
||||||
return getattr(self, '_has_dependency', False)
|
return getattr(self, '_has_dependency', False)
|
||||||
else:
|
return hasattr(self, '_dependencies')
|
||||||
return hasattr(self, '_dependencies')
|
|
||||||
|
|
||||||
def _get_dependencies(self,
|
def _get_dependencies(self,
|
||||||
context):
|
context_od) -> Set[str]:
|
||||||
if context:
|
|
||||||
od = context.cfgimpl_get_description()
|
|
||||||
ret = set(getattr(self, '_dependencies', STATIC_TUPLE))
|
ret = set(getattr(self, '_dependencies', STATIC_TUPLE))
|
||||||
if context and hasattr(od, '_dependencies'):
|
if context_od and hasattr(context_od, '_dependencies'):
|
||||||
return set(od._dependencies) | ret
|
# if context is set in options, add those options
|
||||||
else:
|
return set(context_od._dependencies) | ret
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _add_dependency(self,
|
def _add_dependency(self,
|
||||||
option):
|
option) -> None:
|
||||||
options = self._get_dependencies(None)
|
options = self._get_dependencies(None)
|
||||||
options.add(weakref.ref(option))
|
options.add(weakref.ref(option))
|
||||||
self._dependencies = tuple(options)
|
self._dependencies = tuple(options)
|
||||||
|
|
||||||
def _impl_set_callback(self,
|
def _impl_set_callback(self,
|
||||||
callback,
|
callback: Callable,
|
||||||
callback_params=None):
|
callback_params: Optional[Params]=None) -> None:
|
||||||
|
|
||||||
if callback is None and callback_params is not None:
|
if callback is None and callback_params is not None:
|
||||||
raise ValueError(_("params defined for a callback function but "
|
raise ValueError(_("params defined for a callback function but "
|
||||||
"no callback defined"
|
"no callback defined"
|
||||||
|
@ -276,22 +274,16 @@ class Base(object):
|
||||||
val_call = (callback, callback_params)
|
val_call = (callback, callback_params)
|
||||||
self._val_call = (val, val_call)
|
self._val_call = (val, val_call)
|
||||||
|
|
||||||
def impl_is_optiondescription(self):
|
def impl_is_optiondescription(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_is_dynoptiondescription(self):
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_getname(self):
|
def impl_getname(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
def impl_is_readonly(self):
|
def _set_readonly(self) -> None:
|
||||||
return not isinstance(getattr(self, '_informations', dict()), dict)
|
|
||||||
|
|
||||||
def impl_getproperties(self):
|
|
||||||
return getattr(self, '_properties', frozenset())
|
|
||||||
|
|
||||||
def _set_readonly(self):
|
|
||||||
if not self.impl_is_readonly():
|
if not self.impl_is_readonly():
|
||||||
_setattr = object.__setattr__
|
_setattr = object.__setattr__
|
||||||
dico = self._informations
|
dico = self._informations
|
||||||
|
@ -305,11 +297,17 @@ class Base(object):
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
|
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
|
||||||
|
|
||||||
|
def impl_is_readonly(self) -> str:
|
||||||
|
return not isinstance(getattr(self, '_informations', dict()), dict)
|
||||||
|
|
||||||
|
def impl_getproperties(self) -> FrozenSet[str]:
|
||||||
|
return getattr(self, '_properties', frozenset())
|
||||||
|
|
||||||
def _setsubdyn(self,
|
def _setsubdyn(self,
|
||||||
subdyn):
|
subdyn) -> None:
|
||||||
self._subdyn = weakref.ref(subdyn)
|
self._subdyn = weakref.ref(subdyn)
|
||||||
|
|
||||||
def issubdyn(self):
|
def issubdyn(self) -> bool:
|
||||||
return getattr(self, '_subdyn', None) is not None
|
return getattr(self, '_subdyn', None) is not None
|
||||||
|
|
||||||
def getsubdyn(self):
|
def getsubdyn(self):
|
||||||
|
@ -331,20 +329,17 @@ class Base(object):
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# information
|
# information
|
||||||
def impl_get_information(self,
|
def impl_get_information(self,
|
||||||
key,
|
key: str,
|
||||||
default=undefined):
|
default: Any=undefined) -> Any:
|
||||||
"""retrieves one information's item
|
"""retrieves one information's item
|
||||||
|
|
||||||
:param key: the item string (ex: "help")
|
:param key: the item string (ex: "help")
|
||||||
"""
|
"""
|
||||||
def _is_string(infos):
|
|
||||||
return isinstance(infos, str)
|
|
||||||
|
|
||||||
dico = self._informations
|
dico = self._informations
|
||||||
if isinstance(dico, tuple):
|
if isinstance(dico, tuple):
|
||||||
if key in dico[0]:
|
if key in dico[0]:
|
||||||
return dico[1][dico[0].index(key)]
|
return dico[1][dico[0].index(key)]
|
||||||
elif _is_string(dico):
|
elif isinstance(dico, str):
|
||||||
if key == 'doc':
|
if key == 'doc':
|
||||||
return dico
|
return dico
|
||||||
elif isinstance(dico, dict):
|
elif isinstance(dico, dict):
|
||||||
|
@ -356,8 +351,8 @@ class Base(object):
|
||||||
key))
|
key))
|
||||||
|
|
||||||
def impl_set_information(self,
|
def impl_set_information(self,
|
||||||
key,
|
key: str,
|
||||||
value):
|
value: Any) -> None:
|
||||||
"""updates the information's attribute
|
"""updates the information's attribute
|
||||||
(which is a dictionary)
|
(which is a dictionary)
|
||||||
|
|
||||||
|
@ -384,47 +379,33 @@ class BaseOption(Base):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def __setattr__(self,
|
def __setattr__(self,
|
||||||
name,
|
name: str,
|
||||||
value):
|
value: Any) -> Any:
|
||||||
"""set once and only once some attributes in the option,
|
"""set once and only once some attributes in the option,
|
||||||
like `_name`. `_name` cannot be changed one the option and
|
like `_name`. `_name` cannot be changed once the option is
|
||||||
pushed in the :class:`tiramisu.option.OptionDescription`.
|
pushed in the :class:`tiramisu.option.OptionDescription`.
|
||||||
|
|
||||||
if the attribute `_readonly` is set to `True`, the option is
|
if the attribute `_readonly` is set to `True`, the option is
|
||||||
"frozen" (which has noting to do with the high level "freeze"
|
"frozen" (which has nothing to do with the high level "freeze"
|
||||||
propertie or "read_only" property)
|
propertie or "read_only" property)
|
||||||
"""
|
"""
|
||||||
if name != '_option' and \
|
# never change _name in an option or attribute when object is readonly
|
||||||
not isinstance(value, tuple):
|
if self.impl_is_readonly():
|
||||||
is_readonly = False
|
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
||||||
# never change _name dans _opt
|
' read-only').format(self.__class__.__name__,
|
||||||
if name == '_name':
|
self.impl_get_display_name(),
|
||||||
if self.impl_getname() is not None:
|
name))
|
||||||
#so _name is already set
|
|
||||||
is_readonly = True
|
|
||||||
elif name != '_readonly':
|
|
||||||
is_readonly = self.impl_is_readonly()
|
|
||||||
if is_readonly and (name != '_path' or value != getattr(self, '_path', value)):
|
|
||||||
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
|
||||||
' read-only').format(self.__class__.__name__,
|
|
||||||
self.impl_get_display_name(),
|
|
||||||
name))
|
|
||||||
super(BaseOption, self).__setattr__(name, value)
|
super(BaseOption, self).__setattr__(name, value)
|
||||||
|
|
||||||
def impl_getpath(self):
|
def impl_getpath(self) -> str:
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
def impl_has_callback(self):
|
def impl_has_callback(self) -> bool:
|
||||||
"to know if a callback has been defined or not"
|
"to know if a callback has been defined or not"
|
||||||
return self.impl_get_callback()[0] is not None
|
return self.impl_get_callback()[0] is not None
|
||||||
|
|
||||||
def _impl_valid_string(self,
|
|
||||||
value):
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
|
|
||||||
def impl_get_display_name(self,
|
def impl_get_display_name(self,
|
||||||
dyn_name=None):
|
dyn_name: Base=None) -> str:
|
||||||
name = self.impl_get_information('doc')
|
name = self.impl_get_information('doc')
|
||||||
if name is None or name == '':
|
if name is None or name == '':
|
||||||
if dyn_name is not None:
|
if dyn_name is not None:
|
||||||
|
@ -434,23 +415,23 @@ class BaseOption(Base):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def reset_cache(self,
|
def reset_cache(self,
|
||||||
path,
|
path: str,
|
||||||
values,
|
values: Values,
|
||||||
settings,
|
settings: Settings,
|
||||||
resetted_opts):
|
resetted_opts: List[Base]) -> None:
|
||||||
settings._p_.delcache(path)
|
settings._p_.delcache(path)
|
||||||
settings._pp_.delcache(path)
|
settings._pp_.delcache(path)
|
||||||
if not self.impl_is_optiondescription():
|
if not self.impl_is_optiondescription():
|
||||||
values._p_.delcache(path)
|
values._p_.delcache(path)
|
||||||
|
|
||||||
def impl_is_symlinkoption(self):
|
def impl_is_symlinkoption(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_requires_arg(new_option,
|
def validate_requires_arg(new_option: BaseOption,
|
||||||
multi,
|
multi: bool,
|
||||||
requires,
|
requires: List[dict],
|
||||||
name):
|
name: str) -> Tuple[FrozenSet, Tuple]:
|
||||||
"""check malformed requirements
|
"""check malformed requirements
|
||||||
and tranform dict to internal tuple
|
and tranform dict to internal tuple
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ class BroadcastOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
for val in value.split('.'):
|
for val in value.split('.'):
|
||||||
|
|
|
@ -33,7 +33,8 @@ class DateOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
try:
|
try:
|
||||||
datetime.strptime(value, "%Y-%m-%d")
|
datetime.strptime(value, "%Y-%m-%d")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
|
@ -101,8 +101,6 @@ class DomainnameOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
|
||||||
|
|
||||||
def _valid_length(val):
|
def _valid_length(val):
|
||||||
if len(val) < 1:
|
if len(val) < 1:
|
||||||
raise ValueError(_("invalid length (min 1)"))
|
raise ValueError(_("invalid length (min 1)"))
|
||||||
|
@ -110,6 +108,8 @@ class DomainnameOption(Option):
|
||||||
raise ValueError(_("invalid length (max {0})"
|
raise ValueError(_("invalid length (max {0})"
|
||||||
"").format(part_name_length))
|
"").format(part_name_length))
|
||||||
|
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if self.impl_get_extra('_allow_ip') is True:
|
if self.impl_get_extra('_allow_ip') is True:
|
||||||
try:
|
try:
|
||||||
IP('{0}/32'.format(value))
|
IP('{0}/32'.format(value))
|
||||||
|
|
|
@ -68,7 +68,8 @@ class IPOption(Option):
|
||||||
**kwargs):
|
**kwargs):
|
||||||
# sometimes an ip term starts with a zero
|
# sometimes an ip term starts with a zero
|
||||||
# but this does not fit in some case, for example bind does not like it
|
# but this does not fit in some case, for example bind does not like it
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
for val in value.split('.'):
|
for val in value.split('.'):
|
||||||
|
|
|
@ -32,10 +32,11 @@ class NetmaskOption(Option):
|
||||||
_display_name = _('netmask address')
|
_display_name = _('netmask address')
|
||||||
|
|
||||||
def _validate(self,
|
def _validate(self,
|
||||||
value,
|
value: str,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs) -> None:
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
for val in value.split('.'):
|
for val in value.split('.'):
|
||||||
|
|
|
@ -34,7 +34,8 @@ class NetworkOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
for val in value.split('.'):
|
for val in value.split('.'):
|
||||||
|
|
|
@ -729,7 +729,8 @@ class RegexpOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
match = self._regexp.search(value)
|
match = self._regexp.search(value)
|
||||||
if not match:
|
if not match:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -33,4 +33,5 @@ class PasswordOption(Option):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
|
|
|
@ -102,7 +102,8 @@ class PortOption(Option):
|
||||||
**kwargs):
|
**kwargs):
|
||||||
if isinstance(value, int):
|
if isinstance(value, int):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
if self.impl_get_extra('_allow_range') and ":" in str(value):
|
if self.impl_get_extra('_allow_range') and ":" in str(value):
|
||||||
value = str(value).split(':')
|
value = str(value).split(':')
|
||||||
if len(value) != 2:
|
if len(value) != 2:
|
||||||
|
|
|
@ -36,7 +36,8 @@ class URLOption(DomainnameOption):
|
||||||
value,
|
value,
|
||||||
*args,
|
*args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._impl_valid_string(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_('invalid string'))
|
||||||
match = self.proto_re.search(value)
|
match = self.proto_re.search(value)
|
||||||
if not match:
|
if not match:
|
||||||
raise ValueError(_('must start with http:// or '
|
raise ValueError(_('must start with http:// or '
|
||||||
|
|
Loading…
Reference in New Issue