From 57cebf7b11637efedd735bc8eef20d153dfdffaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Fri, 27 Jan 2023 15:36:05 +0100 Subject: [PATCH] misc: always disable python expression for new values (#72091) --- tests/admin_pages/test_datasource.py | 75 +------------ tests/admin_pages/test_form.py | 108 ++++++++++-------- tests/admin_pages/test_workflow.py | 72 ++++-------- tests/test_fc_auth.py | 5 - tests/test_widgets.py | 162 +++++++++++++-------------- wcs/data_sources.py | 2 +- wcs/fields.py | 2 +- wcs/qommon/form.py | 10 +- wcs/workflows.py | 2 +- 9 files changed, 178 insertions(+), 260 deletions(-) diff --git a/tests/admin_pages/test_datasource.py b/tests/admin_pages/test_datasource.py index c4aa94ad4..232ec38de 100644 --- a/tests/admin_pages/test_datasource.py +++ b/tests/admin_pages/test_datasource.py @@ -183,8 +183,8 @@ def test_data_sources_new(pub): resp.forms[0]['name'] = 'a new data source' resp.forms[0]['description'] = 'description of the data source' - resp.forms[0]['data_source$type'] = 'python' - resp.forms[0]['data_source$value'] = repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) + resp.forms[0]['data_source$type'] = 'jsonvalue' + resp.forms[0]['data_source$value'] = json.dumps([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/settings/data-sources/' resp = resp.follow() @@ -202,9 +202,9 @@ def test_data_sources_new(pub): resp = resp.click('New Data Source') resp.forms[0]['name'] = 'an other data source' resp.forms[0]['description'] = 'description of the data source' - resp.forms[0]['data_source$type'] = 'python' + resp.forms[0]['data_source$type'] = 'jsonvalue' resp = resp.forms[0].submit('data_source$apply') - resp.forms[0]['data_source$value'] = repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) + resp.forms[0]['data_source$value'] = json.dumps([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) resp = resp.forms[0].submit('submit') assert NamedDataSource.count() == 2 @@ -226,43 +226,6 @@ def test_data_sources_users_new(pub): assert 'category_id' not in resp.form.fields -def test_data_sources_type_options(pub): - create_superuser(pub) - - data_source = NamedDataSource(name='foobar') - data_source.store() - - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - - app = login(get_app(pub)) - resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) - assert resp.form['data_source$type'].options == [ - ('None', True, 'None'), - ('json', False, 'JSON URL'), - ('jsonp', False, 'JSONP URL'), - ('geojson', False, 'GeoJSON URL'), - ('python', False, 'Python Expression (deprecated)'), - ('jsonvalue', False, 'JSON Expression'), - ] - - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - - resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) - assert resp.form['data_source$type'].options == [ - ('None', True, 'None'), - ('json', False, 'JSON URL'), - ('jsonp', False, 'JSONP URL'), - ('geojson', False, 'GeoJSON URL'), - ('jsonvalue', False, 'JSON Expression'), - ] - - def test_data_sources_type_options_jsonp(pub): create_superuser(pub) @@ -299,20 +262,7 @@ def test_data_sources_type_options_python(pub): data_source = NamedDataSource(name='foobar') data_source.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - app = login(get_app(pub)) - resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) - assert 'python' in [x[0] for x in resp.form['data_source$type'].options] - - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) assert 'python' not in [x[0] for x in resp.form['data_source$type'].options] @@ -330,24 +280,11 @@ def test_data_sources_agenda_manual_qs_data_type_options(pub): data_source.external = 'agenda_manual' data_source.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - # check expression type is always forced (no python allowed). app = login(get_app(pub)) resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) assert 'qs_data$element0value$type' not in resp.text - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - - resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) - assert 'qs_data$element0value$type' not in resp.text - def test_data_sources_category(pub): create_superuser(pub) @@ -384,8 +321,8 @@ def test_data_sources_category(pub): resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id) resp = resp.click(href=re.compile('^edit$')) resp.form['category_id'] = str(category.id) - resp.form['data_source$type'] = 'python' - resp.form['data_source$value'] = repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) + resp.form['data_source$type'] = 'jsonvalue' + resp.form['data_source$value'] = json.dumps([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) resp = resp.form.submit('submit').follow() data_source.refresh_from_storage() assert str(data_source.category_id) == str(category.id) diff --git a/tests/admin_pages/test_form.py b/tests/admin_pages/test_form.py index e64f02139..04d30fe33 100644 --- a/tests/admin_pages/test_form.py +++ b/tests/admin_pages/test_form.py @@ -1982,6 +1982,10 @@ def test_form_prefill_field(pub): resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False} + formdef.fields = [ + fields.StringField(id='1', label='1st field', prefill={'type': 'formula', 'value': 'foo'}) + ] + formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'Python Expression (deprecated)' resp.form['prefill$value_formula'] = 'True' @@ -1999,6 +2003,10 @@ def test_form_prefill_field(pub): } # check error handling + formdef.fields = [ + fields.StringField(id='1', label='1st field', prefill={'type': 'formula', 'value': 'foo'}) + ] + formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'Python Expression (deprecated)' resp.form['prefill$value_formula'] = ':' @@ -2018,29 +2026,35 @@ def test_form_prefill_type_options(pub): FormDef.wipe() formdef = FormDef() formdef.name = 'form title' - formdef.fields = [fields.StringField(id='1', label='1st field')] + formdef.fields = [ + fields.StringField(id='1', label='1st field', prefill={'type': 'formula', 'value': 'foo'}) + ] formdef.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert resp.forms[0]['prefill$type'].options == [ - ('None', True, 'None'), + ('None', False, 'None'), ('String / Template', False, 'String / Template'), - ('Python Expression (deprecated)', False, 'Python Expression (deprecated)'), + ('Python Expression (deprecated)', True, 'Python Expression (deprecated)'), ('User Field', False, 'User Field'), ('Geolocation', False, 'Geolocation'), ] - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) + formdef.fields = [ + fields.StringField(id='1', label='1st field', prefill={'type': 'string', 'value': 'foo'}) + ] + formdef.store() + resp = app.get('/backoffice/forms/1/fields/1/') + assert resp.forms[0]['prefill$type'].options == [ + ('None', False, 'None'), + ('String / Template', True, 'String / Template'), + ('User Field', False, 'User Field'), + ('Geolocation', False, 'Geolocation'), + ] + formdef.fields = [fields.StringField(id='1', label='1st field')] + formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert resp.forms[0]['prefill$type'].options == [ ('None', True, 'None'), @@ -2195,16 +2209,18 @@ def test_form_edit_item_field_data_source(pub): FormDef.wipe() formdef = FormDef() formdef.name = 'form title' - formdef.fields = [fields.ItemField(id='1', label='1st field')] + formdef.fields = [ + fields.ItemField(id='1', label='1st field', data_source={'type': 'formula', 'value': 'foo'}) + ] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ - ('None', True, 'None'), + ('None', False, 'None'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), - ('python', False, 'Python Expression (deprecated)'), + ('python', True, 'Python Expression (deprecated)'), ('jsonvalue', False, 'JSON Expression'), ] resp = resp.form.submit('submit').follow() @@ -2215,13 +2231,15 @@ def test_form_edit_item_field_data_source(pub): data_source.notify_on_errors = True data_source.store() + formdef.fields = [fields.ItemField(id='1', label='1st field')] + formdef.store() + resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ ('None', True, 'None'), ('foobar', False, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), - ('python', False, 'Python Expression (deprecated)'), ('jsonvalue', False, 'JSON Expression'), ] resp.form['data_mode'].value = 'data-source' @@ -2241,7 +2259,6 @@ def test_form_edit_item_field_data_source(pub): ('foobar', True, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), - ('python', False, 'Python Expression (deprecated)'), ('jsonvalue', False, 'JSON Expression'), ] @@ -2261,7 +2278,6 @@ def test_form_edit_item_field_data_source(pub): ('foobar', True, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), - ('python', False, 'Python Expression (deprecated)'), ('jsonvalue', False, 'JSON Expression'), ] assert ( @@ -2336,14 +2352,13 @@ def test_form_edit_item_field_data_source_with_categories(pub): ) assert ( PyQuery(resp.pyquery('select[name="data_source$type"] optgroup')[1]).find('option').text() - == 'JSON URL JSONP URL Python Expression (deprecated) JSON Expression' + == 'JSON URL JSONP URL JSON Expression' ) assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', 'test', 'json', 'jsonp', - 'python', 'jsonvalue', ] @@ -2386,7 +2401,7 @@ def test_form_edit_item_field_data_source_with_categories(pub): ) assert ( PyQuery(resp.pyquery('select[name="data_source$type"] optgroup')[3]).find('option').text() - == 'JSON URL JSONP URL Python Expression (deprecated) JSON Expression' + == 'JSON URL JSONP URL JSON Expression' ) assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', @@ -2396,7 +2411,6 @@ def test_form_edit_item_field_data_source_with_categories(pub): 'test', 'json', 'jsonp', - 'python', 'jsonvalue', ] @@ -2446,7 +2460,7 @@ def test_form_edit_item_field_data_source_with_carddef_categories(pub): ) assert ( PyQuery(resp.pyquery('select[name="data_source$type"] optgroup')[1]).find('option').text() - == 'JSON URL JSONP URL Python Expression (deprecated) JSON Expression' + == 'JSON URL JSONP URL JSON Expression' ) assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', @@ -2455,7 +2469,6 @@ def test_form_edit_item_field_data_source_with_carddef_categories(pub): 'carddef:baz:card-view', 'json', 'jsonp', - 'python', 'jsonvalue', ] @@ -2483,7 +2496,7 @@ def test_form_edit_item_field_data_source_with_carddef_categories(pub): ) assert ( PyQuery(resp.pyquery('select[name="data_source$type"] optgroup')[2]).find('option').text() - == 'JSON URL JSONP URL Python Expression (deprecated) JSON Expression' + == 'JSON URL JSONP URL JSON Expression' ) assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', @@ -2492,7 +2505,6 @@ def test_form_edit_item_field_data_source_with_carddef_categories(pub): 'carddef:bar', 'json', 'jsonp', - 'python', 'jsonvalue', ] @@ -2586,12 +2598,15 @@ def test_form_edit_items_field(pub): assert FormDef.get(1).fields[0].max_choices == 5 # check prefilling is possible with a template or a Python expression + formdef.refresh_from_storage() + formdef.fields[0].prefill = {'type': 'formula', 'value': 'foo'} + formdef.store() resp = resp.follow() resp = resp.click('Edit', href='1/') assert resp.forms[0]['prefill$type'].options == [ - ('None', True, 'None'), + ('None', False, 'None'), ('String / Template', False, 'String / Template'), - ('Python Expression (deprecated)', False, 'Python Expression (deprecated)'), + ('Python Expression (deprecated)', True, 'Python Expression (deprecated)'), ] # change configuration for datasource @@ -2674,14 +2689,12 @@ def test_form_edit_page_field(pub): assert formdef.fields[0].label == 'foobar' resp = resp.click('Edit', href='%s/' % formdef.fields[0].id) - resp.form['post_conditions$element0$condition$type'] = 'python' - resp.form['post_conditions$element0$condition$value_python'] = 'foo' + resp.form['post_conditions$element0$condition$value_django'] = 'foo' resp.form['post_conditions$element0$error_message'] = 'bar' resp = resp.form.submit('post_conditions$add_element') # check advanced tab is open after adding a line assert resp.pyquery('[aria-selected="true"]').text() == 'Advanced' - resp.form['post_conditions$element1$condition$type'] = 'python' - resp.form['post_conditions$element1$condition$value_python'] = 'foo2' + resp.form['post_conditions$element1$condition$value_django'] = 'foo2' resp = resp.form.submit('submit') assert 'Both condition and error message are required.' in resp.text resp.form['post_conditions$element1$error_message'] = 'bar2' @@ -2689,23 +2702,21 @@ def test_form_edit_page_field(pub): formdef.refresh_from_storage() assert formdef.fields[0].post_conditions == [ - {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'}, - {'condition': {'type': 'python', 'value': 'foo2'}, 'error_message': 'bar2'}, + {'condition': {'type': 'django', 'value': 'foo'}, 'error_message': 'bar'}, + {'condition': {'type': 'django', 'value': 'foo2'}, 'error_message': 'bar2'}, ] resp = resp.click('Edit', href='%s/' % formdef.fields[0].id) - resp.form['post_conditions$element1$condition$type'] = 'django' resp.form['post_conditions$element1$condition$value_django'] = 'foo3' resp = resp.form.submit('submit').follow() formdef.refresh_from_storage() assert formdef.fields[0].post_conditions == [ - {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'}, + {'condition': {'type': 'django', 'value': 'foo'}, 'error_message': 'bar'}, {'condition': {'type': 'django', 'value': 'foo3'}, 'error_message': 'bar2'}, ] # check error in expression resp = resp.click('Edit', href='%s/' % formdef.fields[0].id) - resp.form['post_conditions$element1$condition$type'] = 'django' resp.form['post_conditions$element1$condition$value_django'] = 'foo3 >' resp = resp.form.submit('submit') assert 'syntax error: Unexpected end of expression in if tag.' in resp.text @@ -3027,27 +3038,28 @@ def test_form_page_field_condition_types(pub): formdef = FormDef() formdef.name = 'form title' formdef.fields = [ - fields.PageField(id='0', label='1st page'), + fields.PageField(id='0', label='1st page', condition={'type': 'python', 'value': '"foo"'}), ] formdef.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/0/') assert resp.form['condition$type'].options == [ ('django', False, 'Django Expression'), - ('python', False, 'Python Expression (deprecated)'), + ('python', True, 'Python Expression (deprecated)'), ] - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) + formdef.fields = [ + fields.PageField(id='0', label='1st page', condition={'type': 'django', 'value': 'True'}), + ] + formdef.store() + resp = app.get('/backoffice/forms/1/fields/0/') + assert 'condition$type' not in resp.text + formdef.fields = [ + fields.PageField(id='0', label='1st page'), + ] + formdef.store() resp = app.get('/backoffice/forms/1/fields/0/') assert 'condition$type' not in resp.text diff --git a/tests/admin_pages/test_workflow.py b/tests/admin_pages/test_workflow.py index b8ad31122..473b07353 100644 --- a/tests/admin_pages/test_workflow.py +++ b/tests/admin_pages/test_workflow.py @@ -1242,11 +1242,10 @@ def test_workflows_edit_email_action(pub): assert sendmail.condition is None resp = app.get(item_url) - resp.form['condition$type'] = 'python' - resp.form['condition$value_python'] = 'True' + resp.form['condition$value_django'] = 'True' resp = resp.form.submit('submit') sendmail = Workflow.get(workflow.id).get_status(st1.id).items[0] - assert sendmail.condition == {'type': 'python', 'value': 'True'} + assert sendmail.condition == {'type': 'django', 'value': 'True'} # check "custom_from" is not advertised resp = app.get(item_url) @@ -2561,14 +2560,11 @@ def test_workflows_global_actions_timeout_trigger_anchor_options(pub): action = workflow.add_global_action('Global') action.add_action('modify_criticality') trigger = action.append_trigger('timeout') + trigger.anchor_expression = 'False' + trigger.anchor = 'python' + trigger.timeout = 42 workflow.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - app = login(get_app(pub)) resp = app.get('/backoffice/workflows/%s/global-actions/1/triggers/%s/' % (workflow.id, trigger.id)) assert resp.form['anchor'].options == [ @@ -2578,13 +2574,16 @@ def test_workflows_global_actions_timeout_trigger_anchor_options(pub): ('Arrival in final status', False, 'Arrival in final status'), ('Anonymisation', False, 'Anonymisation'), ('String / Template', False, 'String / Template'), - ('Python Expression (deprecated)', False, 'Python Expression (deprecated)'), + ('Python Expression (deprecated)', True, 'Python Expression (deprecated)'), ] + # check inspect page with python expression, and python disabled + workflow.store() + app.get('/backoffice/workflows/%s/inspect' % workflow.id) # no error - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - + trigger.anchor_expression = '' + trigger.anchor = None + trigger.timeout = None + workflow.store() resp = app.get('/backoffice/workflows/%s/global-actions/1/triggers/%s/' % (workflow.id, trigger.id)) assert resp.form['anchor'].options == [ ('Creation', False, 'Creation'), @@ -2595,13 +2594,6 @@ def test_workflows_global_actions_timeout_trigger_anchor_options(pub): ('String / Template', False, 'String / Template'), ] - # check inspect page with python expression, and python disabled - trigger.anchor_expression = 'False' - trigger.anchor = 'python' - trigger.timeout = 42 - workflow.store() - app.get('/backoffice/workflows/%s/inspect' % workflow.id) # no error - def test_workflows_global_actions_external_workflow_action(pub): FormDef.wipe() @@ -2656,7 +2648,6 @@ def test_workflows_global_actions_external_workflow_action(pub): resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (workflow.id, st.id)) resp.forms[0]['target_mode'] = 'manual' - resp.forms[0]['target_id$type'] = 'template' resp.forms[0]['target_id$value_template'] = '{{ form_var_plop_id }}' resp = resp.forms[0].submit('submit') assert Workflow.get(workflow.id).possible_status[0].items[0].target_mode == 'manual' @@ -2707,7 +2698,6 @@ def test_workflows_external_workflow_action_config(pub): assert "required field" in resp # multiple errors: do as usual resp.forms[0]['slug'] = 'formdef:external' - resp.forms[0]['condition$type'] = 'django' resp.forms[0]['condition$value_django'] = '{{ 42 }}' resp = resp.forms[0].submit('submit') assert 'There were errors processing your form. See below for details.' in resp @@ -2837,7 +2827,6 @@ def test_workflows_create_formdata_action_config(pub): assert 'Please define new mappings' in resp # multiple errors: do as usual resp.forms[0]['formdef_slug'] = 'target-form' - resp.forms[0]['condition$type'] = 'django' resp.forms[0]['condition$value_django'] = '{{ 42 }}' resp = resp.forms[0].submit('submit') assert 'There were errors processing your form. See below for details.' in resp @@ -2949,7 +2938,6 @@ def test_workflows_create_carddata_action_config(pub): assert 'Please define new mappings' in resp # multiple errors: do as usual resp.forms[0]['formdef_slug'] = 'my-card' - resp.forms[0]['condition$type'] = 'django' resp.forms[0]['condition$value_django'] = '{{ 42 }}' resp = resp.forms[0].submit('submit') assert 'There were errors processing your form. See below for details.' in resp @@ -2970,25 +2958,20 @@ def test_workflows_create_formdata_expression_types(pub): st1 = wf.add_status('New') create_formdata = st1.add_action('create_formdata') create_formdata.formdef_slug = target_formdef.url_name + create_formdata.mappings = [ + Mapping(field_id='0', expression='=form_var_toto_string'), + ] wf.store() - if not pub.site_options.has_section('options'): - pub.site_options.add_section('options') - pub.site_options.set('options', 'disable-python-expressions', 'false') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - app = login(get_app(pub)) resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st1.id)) assert resp.form['mappings$element0$expression$type'].options == [ ('template', False, 'Template'), - ('python', False, 'Python Expression (deprecated)'), + ('python', True, 'Python Expression (deprecated)'), ] - pub.site_options.set('options', 'disable-python-expressions', 'true') - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - + create_formdata.mappings = [] + wf.store() resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st1.id)) assert 'mappings$element0$expression$type' not in resp.text @@ -3018,7 +3001,6 @@ def test_workflows_edit_carddata_action_config(pub): assert 'Please define new mappings' in resp # multiple errors: do as usual resp.forms[0]['formdef_slug'] = 'my-card' - resp.forms[0]['condition$type'] = 'django' resp.forms[0]['condition$value_django'] = '{{ 42 }}' resp = resp.forms[0].submit('submit') assert 'There were errors processing your form. See below for details.' in resp @@ -3064,7 +3046,6 @@ def test_workflows_edit_carddata_action(pub): resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id)) resp.forms[0]['target_mode'] = 'manual' - resp.forms[0]['target_id$type'] = 'template' resp.forms[0]['target_id$value_template'] = '{{ form_var_plop_id }}' resp = resp.forms[0].submit('submit') assert Workflow.get(wf.id).possible_status[0].items[0].target_mode == 'manual' @@ -3087,15 +3068,11 @@ def test_workflows_assign_carddata_action_options(pub): app = login(get_app(pub)) - for value in ['false', 'true']: - # no python expressions - pub.site_options.set('options', 'disable-python-expressions', value) - with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: - pub.site_options.write(fd) - resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id)) - assert 'target_id$type' not in resp.text - assert 'user_association_template$type' not in resp.text - assert 'condition$type' not in resp.text + # no python expressions + resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id)) + assert 'target_id$type' not in resp.text + assert 'user_association_template$type' not in resp.text + assert 'condition$type' not in resp.text def test_workflows_assign_carddata_action(pub): @@ -3411,7 +3388,6 @@ def test_workflows_form_action_config(pub): resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id)) resp.form['by$element0'] = '_submitter' resp.form['varname'] = 'myform' - resp.form['condition$type'] = 'django' resp.form['condition$value_django'] = '42' assert 'Edit Fields' not in resp.text assert resp.form.fields['submit'][0]._value == 'Submit and go to fields edition' diff --git a/tests/test_fc_auth.py b/tests/test_fc_auth.py index 23d6ae650..09c031d97 100644 --- a/tests/test_fc_auth.py +++ b/tests/test_fc_auth.py @@ -304,17 +304,14 @@ def test_fc_settings(): resp.forms[0]['user_field_mappings$element0$field_varname'] = 'prenoms' resp.forms[0]['user_field_mappings$element0$value$value_template'] = '[given_name ""]' - resp.forms[0]['user_field_mappings$element0$value$type'] = 'template' resp.forms[0]['user_field_mappings$element0$verified'] = 'Always' resp.forms[0]['user_field_mappings$element1$field_varname'] = 'nom' resp.forms[0]['user_field_mappings$element1$value$value_template'] = '[family_name ""]' - resp.forms[0]['user_field_mappings$element1$value$type'] = 'template' resp.forms[0]['user_field_mappings$element1$verified'] = 'Always' resp.forms[0]['user_field_mappings$element2$field_varname'] = 'email' resp.forms[0]['user_field_mappings$element2$value$value_template'] = '[email ""]' - resp.forms[0]['user_field_mappings$element2$value$type'] = 'template' resp.forms[0]['user_field_mappings$element2$verified'] = 'Always' resp = resp.forms[0].submit('submit').follow() @@ -362,12 +359,10 @@ def test_fc_settings_no_user_profile(): resp.forms[0]['user_field_mappings$element0$field_varname'] = '__name' resp.forms[0]['user_field_mappings$element0$value$value_template'] = '[given_name ""] [family_name ""]' - resp.forms[0]['user_field_mappings$element0$value$type'] = 'template' resp.forms[0]['user_field_mappings$element0$verified'] = 'Always' resp.forms[0]['user_field_mappings$element2$field_varname'] = '__email' resp.forms[0]['user_field_mappings$element2$value$value_template'] = '[email ""]' - resp.forms[0]['user_field_mappings$element2$value$type'] = 'template' resp.forms[0]['user_field_mappings$element2$verified'] = 'Always' resp = resp.forms[0].submit('submit').follow() diff --git a/tests/test_widgets.py b/tests/test_widgets.py index 8efba452f..1f366bf6d 100644 --- a/tests/test_widgets.py +++ b/tests/test_widgets.py @@ -717,68 +717,6 @@ def test_composite_widget(): ) # extra_css_class is present -def test_computed_expression_widget(): - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_template': 'hello world', 'test$type': ['template']}) - assert widget.parse() == 'hello world' - assert not widget.has_error() - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_template': '', 'test$type': ['template']}) - assert widget.parse() is None - assert not widget.has_error() - - # python value left empty - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']}) - assert not widget.has_error() - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$type': ['python']}) - assert not widget.has_error() - - # but field marqued as required - widget = ComputedExpressionWidget('test', required=True) - mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']}) - assert widget.has_error() - - # invalid values - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_python': 'hello world', 'test$type': ['python']}) - assert widget.has_error() - assert widget.get_error().startswith('syntax error') - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_python': '=3', 'test$type': ['python']}) - assert widget.has_error() - assert widget.get_error().startswith('syntax error') - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_python': '{{form_var_foo}}', 'test$type': ['python']}) - assert widget.has_error() - assert 'Python expression cannot contain {{' in widget.get_error() - - widget = ComputedExpressionWidget('test') - mock_form_submission( - req, widget, {'test$value_template': '{{ form_var_xxx }}', 'test$type': ['template']} - ) - assert not widget.has_error() - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_template': '{% if True %}', 'test$type': ['template']}) - assert widget.has_error() - assert widget.get_error().startswith('syntax error in Django template') - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_template': '[form_var_xxx]', 'test$type': ['template']}) - assert not widget.has_error() - - widget = ComputedExpressionWidget('test') - mock_form_submission(req, widget, {'test$value_template': '[end]', 'test$type': ['template']}) - assert widget.has_error() - assert widget.get_error().startswith('syntax error in ezt template') - - def test_wcsextrastringwidget(): widget = WcsExtraStringWidget('test', value='foo', required=True) mock_form_submission(req, widget, {'test': ''}) @@ -1378,10 +1316,69 @@ def test_profile_fields_sorting(): assert [f[1] for f in widget.get_widgets()[0].options] == ['Email', 'Name'] -def test_computed_expression_widget_no_python(): - pub.load_site_options() - pub.site_options.set('options', 'disable-python-expressions', 'true') +def test_computed_expression_widget(): + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_template': 'hello world', 'test$type': ['template']}) + assert widget.parse() == 'hello world' + assert not widget.has_error() + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_template': '', 'test$type': ['template']}) + assert widget.parse() is None + assert not widget.has_error() + + # python value left empty + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']}) + assert not widget.has_error() + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$type': ['python']}) + assert not widget.has_error() + + # but field marqued as required + widget = ComputedExpressionWidget('test', value='=foo', required=True) + mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']}) + assert widget.has_error() + + # invalid values + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_python': 'hello world', 'test$type': ['python']}) + assert widget.has_error() + assert widget.get_error().startswith('syntax error') + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_python': '=3', 'test$type': ['python']}) + assert widget.has_error() + assert widget.get_error().startswith('syntax error') + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_python': '{{form_var_foo}}', 'test$type': ['python']}) + assert widget.has_error() + assert 'Python expression cannot contain {{' in widget.get_error() + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission( + req, widget, {'test$value_template': '{{ form_var_xxx }}', 'test$type': ['template']} + ) + assert not widget.has_error() + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_template': '{% if True %}', 'test$type': ['template']}) + assert widget.has_error() + assert widget.get_error().startswith('syntax error in Django template') + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_template': '[form_var_xxx]', 'test$type': ['template']}) + assert not widget.has_error() + + widget = ComputedExpressionWidget('test', value='=foo') + mock_form_submission(req, widget, {'test$value_template': '[end]', 'test$type': ['template']}) + assert widget.has_error() + assert widget.get_error().startswith('syntax error in ezt template') + + +def test_computed_expression_widget_no_python(): widget = ComputedExpressionWidget('test') form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded') form.widgets.append(widget) @@ -1392,6 +1389,11 @@ def test_computed_expression_widget_no_python(): assert widget.parse() == 'hello world' assert not widget.has_error() + widget = ComputedExpressionWidget('test', value='{{ foo }}') + mock_form_submission(req, widget, {'test$value_template': 'hello world'}) + assert widget.parse() == 'hello world' + assert not widget.has_error() + widget = ComputedExpressionWidget('test') mock_form_submission(req, widget, {'test$value_template': ''}) assert widget.parse() is None @@ -1406,50 +1408,50 @@ def test_computed_expression_widget_no_python(): assert widget.has_error() assert widget.get_error().startswith('syntax error in Django template') - pub.site_options.set('options', 'disable-python-expressions', 'false') - def test_condition_widget(): - widget = ConditionWidget('test') + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded') form.widgets.append(widget) assert '$type' in str(form.render()) - widget = ConditionWidget('test') - mock_form_submission(req, widget, {'test$value_django': 'hello == 1'}) + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) + mock_form_submission(req, widget, {'test$value_django': 'hello == 1', 'test$type': ['django']}) assert widget.parse() == {'type': 'django', 'value': 'hello == 1'} assert not widget.has_error() - widget = ConditionWidget('test') - mock_form_submission(req, widget, {'test$value_django': ''}) + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) + mock_form_submission(req, widget, {'test$value_django': '', 'test$type': ['django']}) assert widget.parse() is None assert not widget.has_error() - widget = ConditionWidget('test') - mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}'}) + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) + mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}', 'test$type': ['django']}) assert widget.has_error() assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'" - widget = ConditionWidget('test') + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) mock_form_submission(req, widget, {'test$value_python': 'hello == 1', 'test$type': ['python']}) assert widget.parse() == {'type': 'python', 'value': 'hello == 1'} assert not widget.has_error() - widget = ConditionWidget('test') + widget = ConditionWidget('test', value={'type': 'python', 'value': 'foo'}) mock_form_submission(req, widget, {'test$value_python': 'hello~', 'test$type': ['python']}) assert widget.has_error() assert widget.get_error().startswith('syntax error:') def test_condition_widget_no_python(): - pub.load_site_options() - pub.site_options.set('options', 'disable-python-expressions', 'true') - widget = ConditionWidget('test') form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded') form.widgets.append(widget) assert '$type' not in str(form.render()) + widget = ConditionWidget('test', value={'type': 'django', 'value': 'foo'}) + form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded') + form.widgets.append(widget) + assert '$type' not in str(form.render()) + widget = ConditionWidget('test') mock_form_submission(req, widget, {'test$value_django': 'hello == 1'}) assert widget.parse() == {'type': 'django', 'value': 'hello == 1'} @@ -1465,8 +1467,6 @@ def test_condition_widget_no_python(): assert widget.has_error() assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'" - pub.site_options.set('options', 'disable-python-expressions', 'false') - def test_emoji_button(): # textual button diff --git a/wcs/data_sources.py b/wcs/data_sources.py index 668eb6f7c..a10fe3cff 100644 --- a/wcs/data_sources.py +++ b/wcs/data_sources.py @@ -60,7 +60,7 @@ class DataSourceSelectionWidget(CompositeWidget): def __init__(self, name, value=None, allowed_source_types=None, disallowed_source_types=None, **kwargs): if allowed_source_types is None: allowed_source_types = {'json', 'jsonp', 'geojson', 'named', 'cards', 'python', 'jsonvalue'} - if get_publisher().has_site_option('disable-python-expressions') and 'python' in allowed_source_types: + if 'python' in allowed_source_types: allowed_source_types.remove('python') if get_publisher().has_site_option('disable-jsonp-sources') and 'jsonp' in allowed_source_types: allowed_source_types.remove('jsonp') diff --git a/wcs/fields.py b/wcs/fields.py index ee3ab611d..5b7a83d1f 100644 --- a/wcs/fields.py +++ b/wcs/fields.py @@ -118,7 +118,7 @@ class PrefillSelectionWidget(CompositeWidget): ('none', _('None')), ('string', _('String / Template')), ] - if not get_publisher().has_site_option('disable-python-expressions'): + if value.get('type') == 'formula': options.append(('formula', _('Python Expression (deprecated)'))) options += [ ('user', _('User Field')), diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py index c992125e3..82516002f 100644 --- a/wcs/qommon/form.py +++ b/wcs/qommon/form.py @@ -3584,13 +3584,13 @@ class ComputedExpressionWidget(CompositeWidget): ) self.has_python = False - if self.allow_python and not get_publisher().has_site_option('disable-python-expressions'): + if self.allow_python and value.get('type') == 'python': self.has_python = True self.add( StringWidget, 'value_python', size=80, - value=value.get('value') if value.get('type') == 'python' else None, + value=value.get('value'), placeholder=value_placeholder, ) self.add( @@ -3709,15 +3709,13 @@ class ConditionWidget(CompositeWidget): value=value.get('value') if value.get('type') == 'django' else None, ) - if kwargs.get('allow_python', True) and not get_publisher().has_site_option( - 'disable-python-expressions' - ): + if kwargs.get('allow_python', True) and value.get('type') == 'python': self.has_python = True self.add( StringWidget, 'value_python', size=80, - value=value.get('value') if value.get('type') == 'python' else None, + value=value.get('value'), ) self.add( SingleSelectWidget, diff --git a/wcs/workflows.py b/wcs/workflows.py index cd097ede0..58150bbc8 100644 --- a/wcs/workflows.py +++ b/wcs/workflows.py @@ -1664,7 +1664,7 @@ class WorkflowGlobalActionTimeoutTrigger(WorkflowGlobalActionTrigger): def form(self, workflow): form = Form(enctype='multipart/form-data') options = self.get_anchor_labels() - if get_publisher().has_site_option('disable-python-expressions'): + if not self.anchor_expression: options.pop('python') options = list(options.items()) form.add( -- 2.39.2