[inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 01 Aug 2013 13:55:11 +0200
branchstable
changeset 9213 312062f53981
parent 9212 0d346a0a1451
child 9214 be05b42b4825
[inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653 In the above changeset, we changed ordered entities to be edited according to mandatory inlined constraints, though this leads to unpredictable order in cases where there are no constraint. This leads to case where inlined relation field may think there is no value related to a mandatory relation, while this is simply because there is a value specified but to an entity that will be created later (together with the relation). To fix this, we've to use the fact that the RelationField.process_form_value return None in cases where there is some entity to be created, while an empty set when there are no linked entity. The new no_value() method allows to differentiate between those different notion of 'no-value'.
web/formfields.py
web/test/data/schema.py
web/test/unittest_views_basecontrollers.py
--- a/web/formfields.py	Thu Aug 01 10:59:52 2013 +0200
+++ b/web/formfields.py	Thu Aug 01 13:55:11 2013 +0200
@@ -506,7 +506,7 @@
             if field is self:
                 try:
                     value = field.process_form_value(form)
-                    if value is None and field.required:
+                    if field.no_value(value) and field.required:
                         raise ProcessFormError(form._cw._("required field"))
                     yield field, value
                 except UnmodifiedField:
@@ -517,6 +517,11 @@
                 for field, value in field.process_posted(form):
                     yield field, value
 
+    @staticmethod
+    def no_value(value):
+        """return True if the value can be considered as no value for the field"""
+        return value is None
+
 
 class StringField(Field):
     """Use this field to edit unicode string (`String` yams type). This field
@@ -1165,6 +1170,12 @@
             eids.add(typed_eid)
         return eids
 
+    @staticmethod
+    def no_value(value):
+        """return True if the value can be considered as no value for the field"""
+        # value is None is the 'not yet ready value, consider the empty set
+        return value is not None and not value
+
 
 _AFF_KWARGS = uicfg.autoform_field_kwargs
 
--- a/web/test/data/schema.py	Thu Aug 01 10:59:52 2013 +0200
+++ b/web/test/data/schema.py	Thu Aug 01 13:55:11 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,9 +15,6 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
 
 from yams.buildobjs import (EntityType, RelationDefinition, SubjectRelation,
                             String, Int, Datetime, Boolean, Float)
--- a/web/test/unittest_views_basecontrollers.py	Thu Aug 01 10:59:52 2013 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Thu Aug 01 13:55:11 2013 +0200
@@ -645,6 +645,34 @@
         finally:
             p.__class__.skip_copy_for = old_skips
 
+    def test_regr_inlined_forms(self):
+        self.schema['described_by_test'].inlined = False
+        try:
+            req = self.request()
+            req.data['eidmap'] = {}
+            req.data['pending_others'] = set()
+            req.data['pending_inlined'] = {}
+            req.form = {'eid': ['X', 'Y'], '__maineid' : 'X',
+
+                        '__type:X': 'Salesterm',
+                        '_cw_entity_fields:X': 'described_by_test-subject',
+                        'described_by_test-subject:X': 'Y',
+
+                        '__type:Y': 'File',
+                        '_cw_entity_fields:Y': 'data-subject',
+                        'data-subject:Y': (u'coucou.txt', Binary('coucou')),
+                        }
+            values_by_eid = dict((eid, req.extract_entity_params(eid, minparams=2))
+                                 for eid in req.edited_eids())
+            editctrl = self.vreg['controllers'].select('edit', req)
+            # don't call publish to enforce select order
+            editctrl.errors = []
+            editctrl._to_create = {}
+            editctrl.edit_entity(values_by_eid['X']) # #3064653 raise ValidationError
+            editctrl.edit_entity(values_by_eid['Y'])
+        finally:
+            self.schema['described_by_test'].inlined = False
+
 
 class ReportBugControllerTC(CubicWebTC):