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

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,
callback,
callback_params,
form,
schema):
if callback_params is not None: if callback_params is not None:
remote = True
for callback_param in callback_params.args: for callback_param in callback_params.args:
if isinstance(callback_param, ParamContext): if isinstance(callback_param, ParamContext):
raise ValueError(_('context is not supported from now for {}').format(path)) raise ValueError(_('context is not supported from now for {}').format(path))
if isinstance(callback_param, ParamOption): if isinstance(callback_param, ParamOption):
if callback.__name__ == 'tiramisu_copy': has_option = True
if self.clearable == 'minimum': if callback.__name__ != 'tiramisu_copy' or '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[callback_param.option.impl_getpath()]['remote'] = True
form[options[callback_param.option]].setdefault('copy', []).append(path) remote = True
remote = False if not has_option and form.get(path, {}).get('remote') == False:
elif options.get(callback_param.option) is not None: if 'expire' in childapi.option.properties():
#form.setdefault(options[callback_param.option], {})
form.setdefault(path, {})
form[path]['remote'] = True
#break
if remote:
if self.remotable == 'none': if self.remotable == 'none':
raise ValueError(_('option {} only works when remotable is not "none"').format(path)) raise ValueError(_('option {} only works when remotable is not "none"').format(path))
form.setdefault(path, {})['remote'] = True form.setdefault(path, {})['remote'] = True
else: elif childapi.owner.isdefault():
if 'expire' not in childapi.property.get() and childapi.owner.isdefault(): # get calculated value and set clearable
schema[path]['value'] = childapi.value.get() schema[path]['value'] = childapi.value.get()
if self.clearable == 'minimum': if self.clearable == 'minimum':
form.setdefault(path, {})['clearable'] = True 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
for exp in expected:
if inverse: if inverse:
act = 'show' act = 'show'
inv_act = 'hide' inv_act = 'hide'
else: else:
act = 'hide' act = 'hide'
inv_act = 'show' inv_act = 'show'
require_obj.requires.setdefault(path, for exp in expected:
self.requires.setdefault(path,
{'expected': {}} {'expected': {}}
)['expected'].setdefault(exp, )['expected'].setdefault(exp,
{}).setdefault(act, {}).setdefault(act,
[]).append(option_path) []).append(option_path)
if isinstance(option, ChoiceOption): if isinstance(option, ChoiceOption):
for value in require_obj.config.unrestraint.option(option_path).value.list(): 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: if value not in expected:
require_obj.requires.setdefault(path, self.requires.setdefault(path,
{'expected': {}} {'expected': {}}
)['expected'].setdefault(value, )['expected'].setdefault(value,
{}).setdefault(inv_act, {}).setdefault(inv_act,
[]).append(option_path) []).append(option_path)
require_obj.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path) self.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,