update todict support and tests

This commit is contained in:
2019-06-21 23:04:04 +02:00
parent 55da00f131
commit 83f05197fb
21 changed files with 2820 additions and 2296 deletions

View File

@@ -257,7 +257,16 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
def defaultmulti(self):
"""Get default value when added a value for a multi option (not for optiondescription)"""
option = self._option_bag.option
return option.impl_getdefault_multi()
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)
if not isinstance(value, list):
ret = value
return ret
def consistencies(self):
"""Get consistencies for an option (not for optiondescription)"""
@@ -556,6 +565,11 @@ class _TiramisuOptionValueChoiceOption:
option = self._option_bag.option
return option.impl_get_values(self._option_bag)
def callbacks(self):
"""Get callbacks for a values"""
option = self._option_bag.option
return option.get_callback()
class _TiramisuOptionValueOptionDescription:

View File

@@ -78,7 +78,7 @@ class PropertiesOptionError(AttributeError):
self.proptype = proptype
self._settings = settings
self.msg = None
super(PropertiesOptionError, self).__init__(None)
super().__init__(None)
def set_orig_opt(self, opt):
self._orig_opt = opt
@@ -168,6 +168,7 @@ class _CommonError:
self.val = val
self.display_type = display_type
self.opt = weakref.ref(opt)
self.name = opt.impl_get_display_name()
self.err_msg = err_msg
self.index = index
super().__init__(self.err_msg)
@@ -178,7 +179,7 @@ class _CommonError:
except AttributeError:
self.prefix = self.tmpl.format(self.val,
self.display_type,
self.opt().impl_get_display_name())
self.name)
msg = self.prefix
if self.err_msg:
if msg:

View File

@@ -75,7 +75,7 @@ msgstr "group_type inconnu: {0}"
#: tiramisu/api.py:753 tiramisu/api.py:1208
msgid "please use .dict() before .updates()"
msgstr "faire .dico() avant .updates()"
msgstr "faire .dict() avant .updates()"
#: tiramisu/api.py:1000
msgid "properties must be a set"

View File

@@ -81,25 +81,34 @@ class ChoiceOption(Option):
properties=properties,
warnings_only=warnings_only)
def get_callback(self):
values = self._choice_values
if isinstance(values, FunctionType):
return (values, getattr(self, '_choice_values_params', {}))
else:
return (None, None)
def impl_get_values(self,
option_bag,
current_opt=undefined):
if current_opt is undefined:
current_opt = self
values = self._choice_values
if isinstance(values, FunctionType):
values, values_params = self.get_callback()
if values is not None:
if option_bag is undefined:
values = undefined
else:
values = carry_out_calculation(current_opt,
callback=values,
callback_params=getattr(self, '_choice_values_params', {}),
callback_params=values_params,
index=None,
config_bag=option_bag.config_bag,
fromconsistency=[])
if values is not undefined and not isinstance(values, list):
raise ConfigError(_('calculated values for {0} is not a list'
'').format(self.impl_getname()))
else:
values = self._choice_values
return values

View File

@@ -359,10 +359,10 @@ class Option(BaseOption):
'{0}'.format(err),
err_index)
warnings.warn_explicit(ValueErrorWarning(val,
self._display_name,
option_bag.ori_option,
'{0}'.format(err),
err_index),
self._display_name,
option_bag.ori_option,
'{0}'.format(err),
err_index),
ValueErrorWarning,
self.__class__.__name__, 0)
@@ -707,9 +707,8 @@ class Option(BaseOption):
for opt_ in [opts[idx_inf], opts[idx_inf + idx_sup + 1]]:
if opt_ == current_opt:
is_current = True
else:
if opt_ not in equal:
equal.append(opt_)
elif opt_ not in equal:
equal.append(opt_)
if equal:
if is_current:
if warnings_only:

View File

@@ -406,7 +406,8 @@ class Settings(object):
def getproperties(self,
option_bag,
apply_requires=True):
apply_requires=True,
search_properties=None):
"""
"""
opt = option_bag.option
@@ -432,7 +433,8 @@ class Settings(object):
opt.impl_getproperties())
if apply_requires:
props |= self.apply_requires(option_bag,
False)
False,
search_properties=search_properties)
props -= self.getpermissives(opt,
path)
if apply_requires:
@@ -457,7 +459,8 @@ class Settings(object):
def apply_requires(self,
option_bag,
readable):
readable,
search_properties=None):
"""carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's
@@ -517,6 +520,8 @@ class Settings(object):
for requires in current_requires:
for require in requires:
exps, action, inverse, transitive, same_action, operator = require
#if search_properties and action not in search_properties:
# continue
breaked = False
for option, expected in exps:
if not isinstance(option, tuple):

View File

@@ -65,6 +65,14 @@ class Values(Cache):
# follower
self._values[nb].append([value])
def _add_new_value(self, index, nb, value):
if index is None or nb == 0:
# not follower or path
self._values[nb].append(value)
else:
# follower
self._values[nb].append([value])
# value
def setvalue(self,
path,

View File

@@ -3,8 +3,9 @@
import warnings
import sys
from copy import copy
from collections import OrderedDict
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError
from itertools import chain
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError, ConfigError
from .setting import undefined
from . import SynDynOption, RegexpOption, ChoiceOption, ParamContext, ParamOption
from .i18n import _
@@ -57,23 +58,21 @@ class Callbacks(object):
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)
continue
has_option = False
if callback_params is not None:
for callback_param in callback_params.args:
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 callback.__name__ != 'tiramisu_copy' or 'expire' in childapi.option.properties():
if self.remotable == 'none':
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
form[callback_param.option.impl_getpath()]['remote'] = True
remote = True
if not has_option and form.get(path, {}).get('remote') == False:
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():
if self.remotable == 'none':
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
form.setdefault(path, {})['remote'] = True
self.tiramisu_web.set_remotable(path, form, childapi)
elif childapi.owner.isdefault():
# get calculated value and set clearable
schema[path]['value'] = childapi.value.get()
@@ -83,7 +82,7 @@ class Callbacks(object):
def manage_callbacks(self, form):
for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
if callback_params is not None:
for callback_param in callback_params.args:
for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy':
opt_path = callback_param.option.impl_getpath()
if form.get(opt_path, {}).get('remote') is not True:
@@ -98,41 +97,39 @@ class Callbacks(object):
class Consistencies(object):
def __init__(self, tiramisu_web):
self.not_equal = []
self.options = {}
self.not_equal = {}
self.tiramisu_web = tiramisu_web
def add(self, path, childapi):
child = childapi.option.get()
if isinstance(child, SynDynOption):
child = child._impl_getopt()
self.options[child] = path
def add(self, path, childapi, form):
if not childapi.option.isoptiondescription():
for consistency in childapi.option.consistencies():
cons_id, func, all_cons_opts, params = consistency
if func == '_cons_not_equal':
options = []
if func == '_cons_not_equal' and params.get('transitive', True) is True:
options_path = []
for option in all_cons_opts:
options_path.append(option()._path)
for idx, option in enumerate(all_cons_opts):
option = option()
options.append(option)
# FIXME transitive
self.not_equal.append((options, params.get('warnings_only')))
paths = options_path.copy()
paths.pop(idx)
warnings_only = params.get('warnings_only') or getattr(option, '_warnings_only', False)
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)
def process(self, form):
for not_equal, warnings_only in self.not_equal:
not_equal_option = []
for option in not_equal:
not_equal_option.append(self.options[option])
for idx, path in enumerate(not_equal_option):
if form.get(path, {}).get('remote') is True:
continue
options = copy(not_equal_option)
options.pop(idx)
form.setdefault(path, {}).setdefault('not_equal',
{'options': []})
form[path]['not_equal']['options'].extend(options)
if warnings_only or getattr(option, '_warnings_only', False):
form[path]['not_equal']['warnings'] = True
for path in self.not_equal:
for warnings_only in self.not_equal[path]:
options = self.not_equal[path][warnings_only]
if path not in form:
form[path] = {}
if 'not_equal' not in form[path]:
form[path]['not_equal'] = []
obj = {'options': options}
if warnings_only:
obj['warnings'] = True
form[path]['not_equal'].append(obj)
class Requires(object):
@@ -140,8 +137,6 @@ class Requires(object):
self.requires = {}
self.options = {}
self.tiramisu_web = tiramisu_web
self.config = tiramisu_web.config
self.remotable = tiramisu_web.remotable
def manage_requires(self,
childapi,
@@ -153,37 +148,36 @@ class Requires(object):
for require in requires:
options, action, inverse, \
transitive, same_action, operator = require
if transitive is False:
if transitive is False or same_action is False or operator == 'and':
# transitive to "False" not supported yet for a requirement
if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"'
''.format(path))
form.setdefault(path, {'key': path})['remote'] = True
return
if same_action is False:
# same_action to "False" not supported yet for a requirement
if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"'
''.format(path))
form.setdefault(path, {'key': path})['remote'] = True
return
if operator == 'and':
# operator "and" not supported yet for a requirement
if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"'
''.format(path))
form.setdefault(path, {'key': path})['remote'] = True
self.tiramisu_web.set_remotable(path, form, childapi)
return
for option, expected in options:
option_path = self.options.get(option)
if option_path is not None and action in action_hide:
option_path = option.impl_getpath()
if action in action_hide:
if isinstance(option, ChoiceOption):
choice_obj = self.tiramisu_web.config.unrestraint.option(option_path)
if choice_obj.value.is_values_callback():
self.tiramisu_web.set_remotable(option_path, form, choice_obj)
return
else:
values = self.tiramisu_web.get_enum(choice_obj,
choice_obj.option.ismulti(),
option_path,
choice_obj.option.properties())
for value in values:
if value not in expected:
self.requires.setdefault(path,
{'expected': {}}
)['expected'].setdefault(value,
{}).setdefault(inv_act,
[]).append(option_path)
if current_action is None:
current_action = action
elif current_action != action:
if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"'
''.format(path))
form.setdefault(option_path, {'key': option_path})['remote'] = True
self.tiramisu_web.set_remotable(option_path, form)
if inverse:
act = 'show'
inv_act = 'hide'
@@ -196,25 +190,9 @@ class Requires(object):
)['expected'].setdefault(exp,
{}).setdefault(act,
[]).append(option_path)
if isinstance(option, ChoiceOption):
choice_obj = self.config.unrestraint.option(option_path)
values = self.tiramisu_web.get_enum(choice_obj,
choice_obj.option.ismulti(),
option_path,
choice_obj.option.properties())
for value in values:
if value not in expected:
self.requires.setdefault(path,
{'expected': {}}
)['expected'].setdefault(value,
{}).setdefault(inv_act,
[]).append(option_path)
self.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path)
else:
if self.remotable == 'none':
raise ValueError('require set for {} but remotable est "none"'
''.format(path))
form.setdefault(option_path, {'key': option_path})['remote'] = True
self.tiramisu_web.set_remotable(option_path, form)
def add(self, path, childapi, form):
#collect id of all options
@@ -231,7 +209,7 @@ class Requires(object):
current_action)
def is_remote(self, path, form):
if self.remotable == 'all':
if self.tiramisu_web.remotable == 'all':
return True
else:
return form.get(path) and form[path].get('remote', False)
@@ -244,7 +222,7 @@ class Requires(object):
if 'default' in values:
for option in values['default'].get('show', []):
if path == option:
form.setdefault(path, {'key': path})['remote'] = True
self.tiramisu_web.set_remotable(path, form)
if not self.is_remote(option, form):
dependencies.setdefault(option,
{'default': {}, 'expected': {}}
@@ -253,7 +231,7 @@ class Requires(object):
dependencies[option]['default']['show'].append(path)
for option in values['default'].get('hide', []):
if path == option:
form.setdefault(path, {'key': path})['remote'] = True
self.tiramisu_web.set_remotable(path, form)
if not self.is_remote(option, form):
dependencies.setdefault(option,
{'default': {}, 'expected': {}}
@@ -265,7 +243,7 @@ class Requires(object):
expected = ''
for option in actions.get('show', []):
if path == option:
form.setdefault(path, {'key': path})['remote'] = True
self.tiramisu_web.set_remotable(path, form)
if not self.is_remote(option, form):
dependencies.setdefault(option,
{'expected': {}}
@@ -275,7 +253,7 @@ class Requires(object):
dependencies[option]['expected'][expected]['show'].append(path)
for option in actions.get('hide', []):
if path == option:
form.setdefault(path, {'key': path})['remote'] = True
self.tiramisu_web.set_remotable(path, form)
if not self.is_remote(option, form):
dependencies.setdefault(option,
{'expected': {}}
@@ -336,6 +314,18 @@ class TiramisuDict:
path = root + '.' + childname
yield path, childapi
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():
parent_path = path.rsplit('.', 1)[0]
parent = self.config.unrestraint.option(parent_path)
leader = next(parent.list())
form.setdefault(leader.option.path(), {})['remote'] = True
def walk(self,
root,
subchildapi,
@@ -345,6 +335,7 @@ class TiramisuDict:
order,
updates_status,
init=False):
error = None
if init:
if form is not None:
self.requires = Requires(self)
@@ -352,113 +343,120 @@ class TiramisuDict:
self.callbacks = Callbacks(self)
else:
init = False
if subchildapi is None:
if root is None:
subchildapi = self.config.unrestraint.option
try:
if subchildapi is None:
if root is None:
subchildapi = self.config.unrestraint.option
else:
subchildapi = self.config.unrestraint.option(root)
isleadership = False
else:
subchildapi = self.config.unrestraint.option(root)
isleadership = False
else:
isleadership = subchildapi.option.isleadership()
leader_len = None
for path, childapi in self.get_list(root, subchildapi):
if isleadership and leader_len is None:
leader_len = childapi.value.len()
props_no_requires = set(childapi.option.properties())
if form is not None:
self.requires.add(path,
childapi,
form)
self.consistencies.add(path,
childapi)
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,
props_no_requires,
updates_status)
if order is not None:
order.append(path)
if childapi.option.isoptiondescription():
web_type = 'optiondescription'
if childapi_option.isleadership():
type_ = 'array'
else:
type_ = 'object'
if schema is not None:
schema[path] = {'properties': OrderedDict(),
'type': type_}
subschema = schema[path]['properties']
else:
subschema = schema
self.walk(path,
childapi,
subschema,
model,
form,
order,
updates_status)
else:
child = childapi_option.get()
childtype = child.__class__.__name__
if childtype == 'SynDynOption':
childtype = child._impl_getopt().__class__.__name__
if childapi_option.issymlinkoption():
web_type = 'symlink'
else:
web_type = childapi_option.type()
value = childapi.option.default()
if value not in [[], None]:
has_value = True
else:
value = None
has_value = False
is_multi = childapi_option.ismulti()
if is_multi:
default = childapi_option.defaultmulti()
if default not in [None, []]:
has_value = True
else:
default = None
else:
default = None
if schema is not None:
self.gen_schema(schema,
childapi,
childapi_option,
path,
props_no_requires,
value,
default,
is_multi,
web_type)
isleadership = subchildapi.option.isleadership()
leader_len = None
for path, childapi in self.get_list(root, subchildapi):
if isleadership and leader_len is None:
leader_len = childapi.value.len()
one_is_remote = False
props_no_requires = set(childapi.option.properties())
if form is not None:
self.gen_form(form,
web_type,
path,
child,
childapi_option,
childtype,
has_value)
if schema is not None:
if web_type != 'symlink':
schema[path]['title'] = childapi_option.doc()
self.add_help(schema[path],
childapi)
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)
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,
props_no_requires,
updates_status)
if order is not None:
order.append(path)
if childapi.option.isoptiondescription():
web_type = 'optiondescription'
if childapi_option.isleadership():
type_ = 'array'
else:
type_ = 'object'
if schema is not None:
schema[path] = {'properties': {},
'type': type_}
subschema = schema[path]['properties']
else:
subschema = schema
self.walk(path,
childapi,
subschema,
model,
form,
order,
updates_status)
else:
child = childapi_option.get()
childtype = child.__class__.__name__
if childtype == 'SynDynOption':
childtype = child._impl_getopt().__class__.__name__
if childapi_option.issymlinkoption():
web_type = 'symlink'
else:
web_type = childapi_option.type()
value = childapi.option.default()
if value == []:
value = None
is_multi = childapi_option.ismulti()
if is_multi:
defaultmulti = 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)
if form is not None:
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.doc()
self.add_help(schema[path],
childapi)
except Exception as err:
if not init:
raise err
error = err
if init and form is not None:
self.callbacks.process(form)
self.requires.process(form)
self.consistencies.process(form)
del self.requires
del self.consistencies
del self.callbacks
if error:
msg = str(error)
del error
raise ConfigError(_('unable to transform tiramisu object to dict: {}').format(msg))
def gen_schema(self,
@@ -468,9 +466,10 @@ class TiramisuDict:
path,
props_no_requires,
value,
default,
defaultmulti,
is_multi,
web_type):
web_type,
form):
schema[path] = {'type': web_type}
if childapi_option.issymlinkoption():
schema[path]['opt_path'] = childapi_option.get().impl_getopt().impl_getpath()
@@ -478,8 +477,8 @@ class TiramisuDict:
if value is not None:
schema[path]['value'] = value
if default is not None:
schema[path]['default'] = default
if defaultmulti is not None:
schema[path]['defaultmulti'] = defaultmulti
if is_multi:
schema[path]['isMulti'] = is_multi
@@ -491,6 +490,12 @@ class TiramisuDict:
schema[path]['autoFreeze'] = True
if web_type == 'choice':
values, values_params = childapi.value.callbacks()
if values_params:
for values_param in chain(values_params.args, values_params.kwargs.values()):
if isinstance(values_param, ParamOption):
self.set_remotable(path, form, childapi)
return
schema[path]['enum'] = self.get_enum(childapi,
is_multi,
path,
@@ -514,26 +519,28 @@ class TiramisuDict:
path,
child,
childapi_option,
childtype,
has_value):
childtype):
obj_form = {}
if path in form:
obj_form.update(form[path])
if not childapi_option.issymlinkoption():
if self.clearable == 'all':
obj_form['clearable'] = True
if has_value and self.clearable != 'none':
if self.clearable != 'none':
obj_form['clearable'] = True
if self.remotable == 'all' or childapi_option.has_dependency():
obj_form['remote'] = True
pattern = childapi_option.pattern()
if pattern is not None:
obj_form['pattern'] = pattern
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 not obj_form.get('remote', False):
pattern = childapi_option.pattern()
if pattern is not None:
obj_form['pattern'] = pattern
if childtype == 'PortOption':
obj_form['min'] = child.impl_get_extra('_min_value')
obj_form['max'] = child.impl_get_extra('_max_value')
if childtype == 'FloatOption':
obj_form['step'] = 'any'
if childtype == 'PortOption':
obj_form['min'] = child.impl_get_extra('_min_value')
obj_form['max'] = child.impl_get_extra('_max_value')
if web_type == 'choice':
obj_form['type'] = 'choice'
elif web_type in INPUTS:
@@ -541,50 +548,67 @@ class TiramisuDict:
if obj_form:
form[path] = obj_form
def calc_raises_properties(self, childapi):
def calc_raises_properties(self,
obj,
childapi):
old_properties = childapi._option_bag.config_bag.properties
del childapi._option_bag.config_bag.properties
ret = childapi.option.properties(only_raises=True)
if 'permissive' not in childapi._option_bag.config_bag.properties:
childapi._option_bag.config_bag.properties = childapi._option_bag.config_bag.properties | {'permissive'}
# 'display=False' means cannot access only without permissive option
# 'hidden=True' means cannot access with or without permissive option
if childapi.option.properties(only_raises=True):
obj['hidden'] = True
childapi._option_bag.config_bag.properties = childapi._option_bag.config_bag.properties - {'permissive'}
if childapi.option.properties(only_raises=True):
obj['display'] = False
childapi._option_bag.config_bag.properties = old_properties
return ret
def _gen_model_properties(self,
childapi,
path,
index,
props_no_requires):
obj = {}
isfollower = childapi.option.isfollower()
if index is None and isfollower:
# cannot calculated requires with follower without index
props = props_no_requires
else:
props = set(childapi.property.get())
if self.calc_raises_properties(childapi):
obj['display'] = False
if not isfollower and childapi.option.ismulti():
if 'empty' in props:
obj = self.gen_properties(props,
isfollower,
childapi.option.ismulti())
self.calc_raises_properties(obj, childapi)
return obj
def gen_properties(self,
properties,
isfollower=False,
ismulti=False):
obj = {}
if not isfollower and ismulti:
if 'empty' in properties:
obj['required'] = True
props.remove('empty')
if 'mandatory' in props:
properties.remove('empty')
if 'mandatory' in properties:
obj['needs_len'] = True
props.remove('mandatory')
elif 'mandatory' in props:
properties.remove('mandatory')
elif 'mandatory' in properties:
obj['required'] = True
props.remove('mandatory')
if 'frozen' in props:
properties.remove('mandatory')
if 'frozen' in properties:
obj['readOnly'] = True
props.remove('frozen')
if 'hidden' in props:
obj['hidden'] = True
props.remove('hidden')
if 'disabled' in props:
obj['hidden'] = True
props.remove('disabled')
if props:
lprops = list(props)
properties.remove('frozen')
#if 'hidden' in properties:
# obj['hidden'] = True
# properties.remove('hidden')
#if 'disabled' in properties:
# obj['hidden'] = True
# properties.remove('disabled')
if properties:
lprops = list(properties)
lprops.sort()
obj['properties'] = lprops
obj['props'] = lprops
return obj
def gen_model(self,
@@ -597,14 +621,11 @@ class TiramisuDict:
if childapi.option.isoptiondescription():
props = set(childapi.property.get())
obj = {}
if self.calc_raises_properties(childapi):
obj['display'] = False
self.calc_raises_properties(obj, childapi)
if props:
lprops = list(props)
lprops.sort()
obj['properties'] = lprops
if 'hidden' in props or 'disabled' in props:
obj['hidden'] = True
try:
self.config.option(path).option.get()
except PropertiesOptionError:
@@ -646,17 +667,27 @@ class TiramisuDict:
obj,
index,
updates_status):
# FIXME unrestraint ...
try:
nchildapi = self.config.option(path, index=index)
with warnings.catch_warnings(record=True) as warns:
value = nchildapi.value.get()
if path in updates_status and index in updates_status[path]:
value = childapi.value.get()
self._get_value_with_exception(obj,
childapi,
warns)
except PropertiesOptionError:
value = childapi.value.get()
warns = []
updates_status[path][index])
del updates_status[path][index]
else:
try:
nchildapi = self.config.option(path, index=index)
with warnings.catch_warnings(record=True) as warns:
value = nchildapi.value.get()
self._get_value_with_exception(obj,
childapi,
warns)
except ValueError as err:
self._get_value_with_exception(obj,
childapi,
[err])
value = self.config.unrestraint.option(path, index=index).value.get()
except PropertiesOptionError as err:
value = childapi.value.get()
if value is not None and value != []:
obj['value'] = value
obj['owner'] = childapi.owner.get()
@@ -666,9 +697,13 @@ class TiramisuDict:
childapi,
values):
for value in values:
if isinstance(value.message, ValueErrorWarning):
if isinstance(value, ValueError):
obj.setdefault('error', [])
obj['error'].append(str(value))
obj['invalid'] = True
elif isinstance(value.message, ValueErrorWarning):
value.message.prefix = ''
if childapi.option.isleader():
if childapi.option.isfollower():
obj.setdefault('invalid', [])
obj['invalid'].append({'error': str(value.message),
'index': value.message.index})
@@ -681,10 +716,19 @@ class TiramisuDict:
obj['warnings'].append(str(value.message))
obj['hasWarnings'] = True
def gen_global(self):
ret = {}
ret['owner'] = self.config.owner.get()
ret['properties'] = list(self.config.property.get())
ret['properties'].sort()
ret['permissives'] = list(self.config.permissive.get())
ret['permissives'].sort()
return ret
def get_form(self, form):
ret = []
buttons = []
dict_form = OrderedDict()
dict_form = {}
for form_ in form:
if 'key' in form_:
dict_form[form_['key']] = form_
@@ -723,7 +767,7 @@ class TiramisuDict:
childapi.value.set(value)
else:
multi = childapi.value.get()
if not multi and index == 0:
if len(multi) < index + 1:
multi.append(value)
else:
multi[index] = value
@@ -744,26 +788,25 @@ class TiramisuDict:
if 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'))
elif update['action'] == 'delete':
self.del_value(childapi,
path,
index)
elif update['action'] == 'add':
if childapi_option.ismulti():
self.add_value(childapi, path, update['value'])
try:
if update['action'] == 'modify':
self.mod_value(childapi,
path,
index,
update.get('value', undefined))
elif update['action'] == 'delete':
self.del_value(childapi,
path,
index)
elif update['action'] == 'add':
if childapi_option.ismulti():
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:
raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path))
else:
raise ValueError(_('unknown action'))
#except ValueError as err:
# updates_status.setdefault(path, {})[index] = err
# continue
raise ValueError(_('unknown action'))
except ValueError as err:
updates_status.setdefault(path, {})[index] = [err]
if warns != []:
updates_status.setdefault(path, {}).setdefault(index, []).extend(warns)
return updates_status
@@ -797,7 +840,7 @@ class TiramisuDict:
updates_status={}):
rootpath = self.root
if build_schema:
schema = OrderedDict()
schema = {}
else:
schema = None
if build_model:
@@ -809,6 +852,7 @@ class TiramisuDict:
buttons = []
else:
form = None
ret = {}
self.walk(rootpath,
None,
schema,
@@ -832,6 +876,7 @@ class TiramisuDict:
ret['schema'] = schema
if build_model:
ret['model'] = model
ret['global'] = self.gen_global()
if build_form:
ret['form'] = form
ret['version'] = '1.0'

View File

@@ -77,7 +77,7 @@ class Values(object):
check_error=True)
# store value in cache
validator = 'validator' in option_bag.config_bag.properties
if not is_cached or validator:
if not option_bag.fromconsistency and (not is_cached or validator):
self._p_.setcache(option_bag.path,
option_bag.index,
value,