todict: better support for callback

This commit is contained in:
Emmanuel Garette 2019-05-09 20:32:43 +02:00
parent 5ea35bf84e
commit 552cd3740d
6 changed files with 97 additions and 98 deletions

View File

@ -14,7 +14,7 @@
"model": {}, "model": {},
"form": { "form": {
"options.integer": { "options.integer": {
"allowedpattern": "[0-9]", "pattern": "^[0-9]+$",
"type": "input" "type": "input"
}, },
"null": [ "null": [

View File

@ -18,7 +18,7 @@
}, },
"form": { "form": {
"options.integer": { "options.integer": {
"allowedpattern": "[0-9]", "pattern": "^[0-9]+$",
"type": "input" "type": "input"
}, },
"null": [ "null": [

View File

@ -21,7 +21,7 @@
"form": { "form": {
"options.integer": { "options.integer": {
"clearable": true, "clearable": true,
"allowedpattern": "[0-9]", "pattern": "^[0-9]+$",
"type": "input" "type": "input"
}, },
"null": [ "null": [

View File

@ -21,7 +21,7 @@
"form": { "form": {
"options.integer": { "options.integer": {
"clearable": true, "clearable": true,
"allowedpattern": "[0-9]", "pattern": "^[0-9]+$",
"type": "input" "type": "input"
}, },
"null": [ "null": [

View File

@ -271,6 +271,7 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
if isinstance(option, RegexpOption): if isinstance(option, RegexpOption):
return option._regexp.pattern return option._regexp.pattern
if type == 'integer': if type == 'integer':
# FIXME negative too!
return r'^[0-9]+$' return r'^[0-9]+$'
if type == 'domainname': if type == 'domainname':
return option.impl_get_extra('_domain_re').pattern return option.impl_get_extra('_domain_re').pattern
@ -384,11 +385,11 @@ class TiramisuOptionProperty(CommonTiramisuOption):
"""Remove new property for an option""" """Remove new property for an option"""
option = self._option_bag.option option = self._option_bag.option
props = self._settings.getproperties(self._option_bag, props = self._settings.getproperties(self._option_bag,
apply_requires=False) apply_requires=False)
self._settings.setproperties(self._option_bag.path, self._settings.setproperties(self._option_bag.path,
props - {prop}, props - {prop},
self._option_bag, self._option_bag,
self._option_bag.config_bag.context) self._option_bag.config_bag.context)
def reset(self): def reset(self):
"""Reset all personalised properties""" """Reset all personalised properties"""

View File

@ -46,68 +46,54 @@ class Callbacks(object):
def add(self, def add(self,
path, path,
childapi, childapi,
options,
schema, schema,
force_store_value): force_store_value):
self.callbacks.append((path, childapi, options, schema, force_store_value)) if self.remotable == 'all' or childapi.option.isoptiondescription():
return
callback, callback_params = 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 manage_callbacks(self, def process_properties(self, form):
path, for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
childapi, has_option = False
options, if callback_params is not None:
callback, for callback_param in callback_params.args:
callback_params, if isinstance(callback_param, ParamContext):
form, raise ValueError(_('context is not supported from now for {}').format(path))
schema): if isinstance(callback_param, ParamOption):
if callback_params is not None: has_option = True
remote = True if callback.__name__ != 'tiramisu_copy' or 'expire' in childapi.option.properties():
for callback_param in callback_params.args: if self.remotable == 'none':
if isinstance(callback_param, ParamContext): raise ValueError(_('option {} only works when remotable is not "none"').format(path))
raise ValueError(_('context is not supported from now for {}').format(path)) form[callback_param.option.impl_getpath()]['remote'] = True
if isinstance(callback_param, ParamOption): remote = True
if callback.__name__ == 'tiramisu_copy': if not has_option and form.get(path, {}).get('remote') == False:
if self.clearable == 'minimum': if 'expire' in childapi.option.properties():
form.setdefault(path, {})['clearable'] = True if self.remotable == 'none':
if form.get(path, {}).get('remote') is not True and form[options[callback_param.option]].get('remote', False) is not True: raise ValueError(_('option {} only works when remotable is not "none"').format(path))
form.setdefault(options[callback_param.option], {}) form.setdefault(path, {})['remote'] = True
form[options[callback_param.option]].setdefault('copy', []).append(path) elif childapi.owner.isdefault():
remote = False # get calculated value and set clearable
elif options.get(callback_param.option) is not None: schema[path]['value'] = childapi.value.get()
#form.setdefault(options[callback_param.option], {}) if self.clearable == 'minimum':
form.setdefault(path, {}) form.setdefault(path, {})['clearable'] = True
form[path]['remote'] = True
#break
if remote:
if self.remotable == 'none':
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
form.setdefault(path, {})['remote'] = True
else:
if 'expire' not in childapi.property.get() and childapi.owner.isdefault():
schema[path]['value'] = childapi.value.get()
if self.clearable == 'minimum':
form.setdefault(path, {})['clearable'] = True
else:
if self.remotable == 'none':
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
# FIXME is not default, show calculate
form.setdefault(path, {})['remote'] = True
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:
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:
form.setdefault(opt_path, {})
form[opt_path].setdefault('copy', []).append(path)
def process(self, def process(self,
form): form):
for path, childapi, options, schema, force_store_value in self.callbacks: self.process_properties(form)
if not childapi.option.isoptiondescription(): self.manage_callbacks(form)
callback, callback_params = childapi.option.callbacks()
if callback is not None:
if force_store_value and self.clearable != 'all':
return
self.manage_callbacks(path,
childapi,
options,
callback,
callback_params,
form,
schema)
class Consistencies(object): class Consistencies(object):
@ -158,7 +144,6 @@ class Requires(object):
self.remotable = tiramisu_web.remotable self.remotable = tiramisu_web.remotable
def manage_requires(self, def manage_requires(self,
require_obj,
childapi, childapi,
path, path,
form, form,
@ -170,58 +155,63 @@ class Requires(object):
transitive, same_action, operator = require transitive, same_action, operator = require
if transitive is False: if transitive is False:
# transitive to "False" not supported yet for a requirement # transitive to "False" not supported yet for a requirement
if require_obj.remotable == 'none': if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"' raise ValueError('require set for {} but remotable is "none"'
''.format(path)) ''.format(path))
form.setdefault(path, {'key': path})['remote'] = True form.setdefault(path, {'key': path})['remote'] = True
return return
if same_action is False: if same_action is False:
# same_action to "False" not supported yet for a requirement # same_action to "False" not supported yet for a requirement
if require_obj.remotable == 'none': if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"' raise ValueError('require set for {} but remotable is "none"'
''.format(path)) ''.format(path))
form.setdefault(path, {'key': path})['remote'] = True form.setdefault(path, {'key': path})['remote'] = True
return return
if operator == 'and': if operator == 'and':
# operator "and" not supported yet for a requirement # operator "and" not supported yet for a requirement
if require_obj.remotable == 'none': if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"' raise ValueError('require set for {} but remotable is "none"'
''.format(path)) ''.format(path))
form.setdefault(path, {'key': path})['remote'] = True form.setdefault(path, {'key': path})['remote'] = True
return return
for option, expected in options: for option, expected in options:
option_path = require_obj.options.get(option) option_path = self.options.get(option)
if option_path is not None and action in action_hide: if option_path is not None and action in action_hide:
if current_action is None: if current_action is None:
current_action = action current_action = action
elif current_action != action: elif current_action != action:
if require_obj.remotable == 'none': if self.remotable == 'none':
raise ValueError('require set for {} but remotable is "none"' raise ValueError('require set for {} but remotable is "none"'
''.format(path)) ''.format(path))
form.setdefault(option_path, {'key': option_path})['remote'] = True form.setdefault(option_path, {'key': option_path})['remote'] = True
if inverse:
act = 'show'
inv_act = 'hide'
else:
act = 'hide'
inv_act = 'show'
for exp in expected: for exp in expected:
if inverse: self.requires.setdefault(path,
act = 'show' {'expected': {}}
inv_act = 'hide' )['expected'].setdefault(exp,
else: {}).setdefault(act,
act = 'hide' []).append(option_path)
inv_act = 'show' if isinstance(option, ChoiceOption):
require_obj.requires.setdefault(path, choice_obj = self.config.unrestraint.option(option_path)
{'expected': {}} values = self.tiramisu_web.get_enum(choice_obj,
)['expected'].setdefault(exp, choice_obj.option.ismulti(),
{}).setdefault(act, option_path,
[]).append(option_path) choice_obj.option.properties())
if isinstance(option, ChoiceOption): for value in values:
for value in require_obj.config.unrestraint.option(option_path).value.list(): if value not in expected:
if value not in expected: self.requires.setdefault(path,
require_obj.requires.setdefault(path, {'expected': {}}
{'expected': {}} )['expected'].setdefault(value,
)['expected'].setdefault(value, {}).setdefault(inv_act,
{}).setdefault(inv_act, []).append(option_path)
[]).append(option_path) self.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path)
require_obj.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path)
else: else:
if require_obj.remotable == 'none': if self.remotable == 'none':
raise ValueError('require set for {} but remotable est "none"' raise ValueError('require set for {} but remotable est "none"'
''.format(path)) ''.format(path))
form.setdefault(option_path, {'key': option_path})['remote'] = True form.setdefault(option_path, {'key': option_path})['remote'] = True
@ -234,8 +224,7 @@ class Requires(object):
self.options[child] = path self.options[child] = path
current_action = None current_action = None
self.manage_requires(self, self.manage_requires(childapi,
childapi,
path, path,
form, form,
ACTION_HIDE, ACTION_HIDE,
@ -384,7 +373,6 @@ class TiramisuDict:
childapi) childapi)
self.callbacks.add(path, self.callbacks.add(path,
childapi, childapi,
self.requires.options,
schema, schema,
'force_store_value' in props_no_requires) 'force_store_value' in props_no_requires)
childapi_option = childapi.option childapi_option = childapi.option
@ -503,12 +491,22 @@ class TiramisuDict:
schema[path]['autoFreeze'] = True schema[path]['autoFreeze'] = True
if web_type == 'choice': if web_type == 'choice':
schema[path]['enum'] = childapi.value.list() schema[path]['enum'] = self.get_enum(childapi,
empty_is_required = not childapi.option.isfollower() and is_multi is_multi,
if (empty_is_required and not 'empty' in props_no_requires) or \ path,
(not empty_is_required and not 'mandatory' in props_no_requires): props_no_requires)
schema[path]['enum'] = [''] + list(schema[path]['enum'])
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
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, def gen_form(self,
form, form,