Projet

Général

Profil

0001-forms-make-sure-latest-live-data-are-used-to-evaluat.patch

Frédéric Péters, 11 juillet 2018 11:04

Télécharger (5,17 ko)

Voir les différences:

Subject: [PATCH] forms: make sure latest live data are used to evaluate
 conditions (#25197)

 tests/test_form_pages.py | 41 ++++++++++++++++++++++++++++++++++++++++
 wcs/fields.py            | 16 +++++++++-------
 wcs/forms/root.py        |  6 +++++-
 3 files changed, 55 insertions(+), 8 deletions(-)
tests/test_form_pages.py
993 993
    resp = resp.forms[0].submit('submit')
994 994
    assert 'Check values then click submit.' in resp.body
995 995

  
996
def test_form_multi_page_conditions_and_post_conditions(pub):
997
    formdef = create_formdef()
998
    formdef.fields = [
999
        fields.PageField(id='0', label='1st page', type='page',
1000
            post_conditions=[{
1001
                'condition': {'type': 'python', 'value': 'form_var_bar == "bar"'},
1002
                'error_message': 'You shall not pass.'}]),
1003
        fields.StringField(id='1', label='string', varname='bar'),
1004
        fields.PageField(id='3', label='2nd page', type='page'),
1005
    ]
1006

  
1007
    formdef.store()
1008
    formdef.data_class().wipe()
1009

  
1010
    resp = get_app(pub).get('/test/')
1011
    resp.form['f1'] = 'bar'
1012
    resp = resp.form.submit('submit')
1013
    assert_current_page(resp, '2nd page')
1014

  
1015
    resp = get_app(pub).get('/test/')
1016
    resp.form['f1'] = 'foo'
1017
    resp = resp.form.submit('submit')
1018
    assert 'You shall not pass.' in resp.body
1019

  
1020
    # add a conditional page, this will cause pages to be evaluated first
1021
    # (and would trigger #25197)
1022
    formdef.fields.append(
1023
        fields.PageField(id='4', label='3rd page', type='page',
1024
            condition={'type': 'python', 'value': 'True'}))
1025
    formdef.store()
1026

  
1027
    resp = get_app(pub).get('/test/')
1028
    resp.form['f1'] = 'bar'
1029
    resp = resp.form.submit('submit')
1030
    assert_current_page(resp, '2nd page')
1031

  
1032
    resp = get_app(pub).get('/test/')
1033
    resp.form['f1'] = 'foo'
1034
    resp = resp.form.submit('submit')
1035
    assert 'You shall not pass.' in resp.body
1036

  
996 1037
def test_form_multi_page_page_name_as_title(pub):
997 1038
    formdef = create_formdef()
998 1039
    formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
wcs/fields.py
1501 1501
        # they will shadow formdata context variables with their new "live"
1502 1502
        # value, this may be useful when evaluating data sources.
1503 1503
        class ConditionVars(object):
1504
            def __init__(self, id_dict_var):
1505
                # keep track of reference dictionary
1506
                self.id_dict_var = id_dict_var
1507

  
1504 1508
            def get_substitution_variables(self):
1505 1509
                return form_live_data
1506 1510

  
1507 1511
            def __eq__(self, other):
1508
                # Assume all ConditionVars are equal (as they are because they
1509
                # are created using the same live data); this avoids filling
1512
                # Assume all ConditionVars are equal when initialized with
1513
                # the same live data dictionary; this avoids filling
1510 1514
                # the substitution sources with duplicates and invalidating its
1511 1515
                # cache.
1512
                try:
1513
                    return self.__class__.__name__ == other.__class__.__name__
1514
                except AttributeError:
1515
                    return False
1516
                return self.id_dict_var == getattr(other, 'id_dict_var', None)
1517

  
1516 1518
        if dict_vars is not None:
1517 1519
            # Add them only if there is a real dict_vars in context,
1518 1520
            # ie do nothing on first page condition
1519
            get_publisher().substitutions.feed(ConditionVars())
1521
            get_publisher().substitutions.feed(ConditionVars(id(dict_vars)))
1520 1522

  
1521 1523
        data = get_publisher().substitutions.get_context_variables()
1522 1524
        # 2) add live data as var_ variables for local evaluation only, for
wcs/forms/root.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import copy
17 18
import json
18 19
import time
19 20
from StringIO import StringIO
......
718 719
            page_error_messages = []
719 720
            if form.get_submit() == 'submit' and page:
720 721
                post_conditions = page.post_conditions or []
721
                form_data = session.get_by_magictoken(magictoken, {})
722
                # create a new dictionary to hold live data, this makes sure
723
                # a new ConditionsVars will get added to the substitution
724
                # variables.
725
                form_data = copy.copy(session.get_by_magictoken(magictoken, {}))
722 726
                data = self.formdef.get_data(form)
723 727
                form_data.update(data)
724 728
                for i, post_condition in enumerate(post_conditions):
725
-