general: add a NoneFieldVar for None values (#63889) #134

Merged
lguerin merged 1 commits from wip/63889-nonefieldvar into main 2023-05-12 12:20:17 +02:00
5 changed files with 29 additions and 9 deletions

View File

@ -74,6 +74,7 @@ def test_inspect_page(pub, local_user):
fields.ItemField(id='3', label='3rd field', type='item', data_source=datasource, varname='foo'),
fields.FileField(id='4', label='file field', type='file', varname='file'),
fields.BlockField(id='5', label='Block Data', varname='blockdata', type='block:foobar', max_items=3),
fields.StringField(id='6', label='Empty', varname='empty', type='string'),
]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
@ -109,6 +110,7 @@ def test_inspect_page(pub, local_user):
],
'schema': {}, # not important here
},
'6': None,
'0_display': 'plop poulpe',
}
formdata.jump_status('new')
@ -186,6 +188,11 @@ def test_inspect_page(pub, local_user):
pq('[title="form_var_blockdata_1_string"]').children('a').attr('href')
== 'http://example.net/backoffice/forms/blocks/%s/1/' % block.id
)
assert pq('[title="form_var_empty"]').children('a').attr('title') == 'Empty'
assert (
pq('[title="form_var_empty"]').children('a').attr('href')
== 'http://example.net/backoffice/forms/%s/fields/6/' % formdef.id
)
# don't show «unusable» variables
assert 'form_f1' not in resp.text

View File

@ -28,7 +28,7 @@ from wcs.qommon.substitution import CompatibilityNamesDict
from wcs.qommon.template import Template
from wcs.qommon.upload_storage import PicklableUpload
from wcs.sql_criterias import FtsMatch
from wcs.variables import LazyFormData
from wcs.variables import LazyFormData, NoneFieldVar
from wcs.wf.create_formdata import JournalAssignationErrorPart
from wcs.wf.register_comment import JournalEvolutionPart
from wcs.wf.wscall import JournalWsCallErrorPart
@ -211,13 +211,13 @@ def test_file_field(pub, formdef):
formdata.data = {'0': None}
substvars = formdata.get_substitution_variables()
assert substvars['form_var_foo'] is None
assert isinstance(substvars['form_var_foo'], NoneFieldVar)
assert substvars['form_var_foo_raw'] is None
assert substvars['form_var_foo_url'] is None
formdata.data = {}
substvars = formdata.get_substitution_variables()
assert substvars['form_var_foo'] is None
assert isinstance(substvars['form_var_foo'], NoneFieldVar)
assert substvars['form_var_foo_raw'] is None
assert substvars['form_var_foo_url'] is None
@ -2035,7 +2035,10 @@ def test_lazy_variables_missing(pub, variable_test_data):
pub.substitutions.feed(formdata)
for mode in (None, 'lazy'):
context = pub.substitutions.get_context_variables(mode=mode)
assert context['form_var_foo_foo_baz_baz'] is None
if mode == 'lazy':
assert isinstance(context['form_var_foo_foo_baz_baz'], NoneFieldVar)
else:
assert context['form_var_foo_foo_baz_baz'] is None
assert context['form_var_foo_foo'] == 'bar'
with pytest.raises(KeyError):
assert context['form_var_foo_foo_xxx'] == 'bar'
@ -2119,7 +2122,10 @@ def test_lazy_map_variable(pub, variable_test_data):
pub.substitutions.reset()
pub.substitutions.feed(formdef)
with pub.substitutions.temporary_feed(formdata, force_mode=mode):
assert WorkflowStatusItem.compute('=form_var_map', raises=True) is None
if mode == 'lazy':
assert isinstance(WorkflowStatusItem.compute('=form_var_map', raises=True), NoneFieldVar)
else:
assert WorkflowStatusItem.compute('=form_var_map', raises=True) is None
assert (
WorkflowStatusItem.compute('{{ form_var_map|distance:"1;2"|floatformat }}', raises=True) == ''
)

View File

@ -64,7 +64,7 @@ from wcs.sql_criterias import (
StrictNotEqual,
get_field_id,
)
from wcs.variables import LazyFieldVar, LazyList
from wcs.variables import LazyFieldVar, LazyList, NoneFieldVar
from wcs.workflows import WorkflowStatusItem, item_classes, template_on_formdata
from ..qommon import _, audit, errors, ezt, force_str, get_cfg, misc, ngettext, ods, pgettext_lazy, template
@ -3712,6 +3712,8 @@ class FormBackOfficeStatusPage(FormStatusPage):
r += htmltext(' <a title="%s" href="%s"></a>' % (v._field.label, field_url))
r += htmltext('</code>')
r += htmltext(' <div class="value"><span>%s</span>') % v
if isinstance(v, NoneFieldVar):
r += htmltext(' <span class="type">(%s)</span>') % _('no value')
elif isinstance(v, (types.FunctionType, types.MethodType)):
continue
elif k.endswith('form_parent') and isinstance(v, CompatibilityNamesDict) and ('form' in v):

View File

@ -544,9 +544,9 @@ def add(term1, term2):
'''replace the "add" native django filter'''
# consider None content as the empty string
if term1 is None:
if unlazy(term1) is None:
term1 = ''
if term2 is None:
if unlazy(term2) is None:
term2 = ''
# return available number if the other term is the empty string

View File

@ -1033,7 +1033,7 @@ class LazyFormDataVar:
# let boolean pass through, to get None handled as False
if field.type != 'bool':
if self._data.get(field.id) is None:
return None
return NoneFieldVar(**self.get_field_kwargs(field))
if str(field.id) not in self._data:
raise KeyError(key)
@ -1150,6 +1150,11 @@ class LazyFieldVar:
raise AssertionError('lazy cannot be pickled')
class NoneFieldVar(LazyFieldVar):
def get_value(self):
return None
class LazyFieldVarComplex(LazyFieldVar):
def has_live_data_source(self):
real_data_source = self._field.get_real_data_source()