[PATCH seda v2] [hook] Don't check for unhandled cardinality on the seda_binary_data_object relation

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Oct 11 14:47:55 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1507706643 -7200
#      Wed Oct 11 09:24:03 2017 +0200
# Node ID 80c39123d0299d4f0e1d2718ea08c479a204f082
# Parent  71c3d7cf079a7206211a22bedcce9922a29ca7a4
# Available At https://hg.logilab.org/review/cubes/seda
#              hg pull https://hg.logilab.org/review/cubes/seda -r 80c39123d029
[hook] Don't check for unhandled cardinality on the seda_binary_data_object relation

in case the profile is a simplified profile. This is because this relation is
there because of the SEDA 2 underlying model, where all data objects are below
the transfer node, but it is not used in SEDA 0.2 and 1.0, where data
objects are dispatched under the archive units tree. So we don't want to prevent
having several data objects with cardinality != 1 at different level of the
tree.

Closes extranet #37372358

diff --git a/cubicweb_seda/hooks.py b/cubicweb_seda/hooks.py
--- a/cubicweb_seda/hooks.py
+++ b/cubicweb_seda/hooks.py
@@ -1,6 +1,6 @@
-# copyright 2016-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr -- mailto:contact at logilab.fr
 #
 # This program is free software: you can redistribute it and/or modify it under
 # the terms of the GNU Lesser General Public License as published by the Free
 # Software Foundation, either version 2.1 of the License, or (at your option)
@@ -412,11 +412,11 @@ class UpdatedCardinalityCheckedEntityHoo
         rtype, role = icontained.parent_relation()
         CheckChildrenUnhandledCardinalityOp.get_instance(self._cw).add_data(
             (parent.eid, rtype, self.entity.eid))
 
 
-class CheckChildrenUnhandledCardinalityOp(hook.DataOperationMixIn, hook.Operation):
+class CheckChildrenUnhandledCardinalityOp(hook.DataOperationMixIn, hook.LateOperation):
     """Check we don't run into the case of an with more than one child through a
     same relation with `user_cardinality != '1'` (otherwise it won't be
     validable by RelaxNG validator like Jing).
 
     Expect (parent_eid, rtype, error_entity_eid) to be added into the data container:
@@ -426,15 +426,38 @@ class CheckChildrenUnhandledCardinalityO
     * name of the relation to retrieve its children (expected to be an object
       relation),
 
     * eid of the entity on which the `ValidationError` will be raised in case of
       error.
+
+    This is a late operation since it has to be executed once the 'container' relation is set.
     """
 
     def precommit_event(self):
         for parent_eid, rtype, added_entity_eid in self.get_data():
             parent = self.cnx.entity_from_eid(parent_eid)
+            # if the container is a simplified profile, allow to have several
+            # entities with cardinality != 1 under the seda_binary_data_object
+            # relation because data objects are all linked to the transfer
+            # through this relation, but this is only relevant for SEDA 2 export
+            # and we don't want to prevent this in profiles for SEDA 0.2 and 1.0
+            # export.
+            if rtype == 'seda_binary_data_object':
+                if parent.cw_etype == 'SEDAArchiveTransfer':
+                    container = parent
+                else:
+                    if not parent.container:
+                        # we may have to clear the container cache if the parent has
+                        # been added in the same transaction
+                        parent.cw_clear_relation_cache('container', 'subject')
+                    container = parent.cw_adapt_to('IContained').container
+                if container.cw_etype != 'SEDAArchiveTransfer':
+                    # component archive unit, don't check the relation, it will
+                    # be checked upon import of the component into a transfer
+                    continue
+                if container.simplified_profile:
+                    continue
             has_non_single_cardinality = False
             # sort to attempt to return the child with the greatest eid
             for child in sorted(parent.related(rtype, 'object', entities=True),
                                 key=lambda x: x.eid):
                 if child.user_cardinality != '1':
diff --git a/test/test_hooks.py b/test/test_hooks.py
--- a/test/test_hooks.py
+++ b/test/test_hooks.py
@@ -1,6 +1,6 @@
-# copyright 2016-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr -- mailto:contact at logilab.fr
 #
 # This program is free software: you can redistribute it and/or modify it under
 # the terms of the GNU Lesser General Public License as published by the Free
 # Software Foundation, either version 2.1 of the License, or (at your option)
@@ -148,10 +148,21 @@ class ValidationHooksTC(CubicWebTC):
                                          seda_binary_data_object=transfer)
             cnx.commit()
             with self.assertValidationError(cnx):
                 testutils.create_data_object(unit_alt_seq, user_cardinality=u'1..n',
                                              seda_binary_data_object=transfer)
+            unit2, unit2_alt, unit2_alt_seq = testutils.create_archive_unit(transfer)
+            with self.assertValidationError(cnx):
+                testutils.create_data_object(unit2_alt_seq, user_cardinality=u'0..n',
+                                             seda_binary_data_object=transfer)
+            # though adding a data object with card != to another archive unit
+            # *on a simplified profile* is fine
+            transfer.cw_set(simplified_profile=True)
+            unit2, unit2_alt, unit2_alt_seq = testutils.create_archive_unit(transfer)
+            testutils.create_data_object(unit2_alt_seq, user_cardinality=u'0..n',
+                                         seda_binary_data_object=transfer)
+            cnx.commit()
 
     def test_multiple_child_unhandled_cardinality_keyword(self):
         with self.admin_access.cnx() as cnx:
             transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
             unit, unit_alt, unit_alt_seq = testutils.create_archive_unit(transfer)


More information about the saem-devel mailing list