[PATCH 3 of 3 saem v4] [hook] Don't log relations from a concept to another container on the concept

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Jul 19 14:36:37 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1500451412 -7200
#      Wed Jul 19 10:03:32 2017 +0200
# Node ID 6a21c76d77468be4763c81bafe5a37987827566d
# Parent  e615a76f44e044b97b065f85b5c7f20828d5cdcc
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r 6a21c76d7746
[hook] Don't log relations from a concept to another container on the concept

Concept are mostly use as 'attribute' caracterizing another container (profile
or authority record), we don't expect action of (un)linking to a concept to be
considered from the concept POV (and so, we don't want update of the concept's
scheme modification_date).

Related to extranet #29296087

diff --git a/cubicweb_saem_ref/hooks.py b/cubicweb_saem_ref/hooks.py
--- a/cubicweb_saem_ref/hooks.py
+++ b/cubicweb_saem_ref/hooks.py
@@ -92,17 +92,33 @@ def qualify_relation(subj, rtype, obj):
         return [('parent', 'subject', s_adapter)]
     # from here, we can assume rtype is not a parentship relation. Notice the relation may concerns
     # two distinct containers
     assert s_adapter or o_adapter
     result = []
-    if s_adapter is not None:
+    # if relation concerns two containers and one of the entity is a concept,
+    # don't log action on the concept
+    if s_adapter is not None and (o_adapter is None or _log_relation(rtype, subj, obj)):
         result.append(('border', 'subject', s_adapter))
-    if o_adapter is not None:
+    if o_adapter is not None and (s_adapter is None or _log_relation(rtype, obj, subj)):
         result.append(('border', 'object', o_adapter))
     return result
 
 
+def _log_relation(rtype, entity, target):
+    """Return boolean indicating wether the relation modification should be logged.
+
+    This is called when relation's ends are in different containers, with
+    `entity` as the potentiel activity holder and `target` the other relation's
+    end.
+    """
+    # if entity is a scheme or concept, only log if the other ends is also a
+    # concept or scheme
+    if entity.cw_etype in ('Concept', 'ConceptScheme'):
+        return target.cw_etype in ('Concept', 'ConceptScheme')
+    return True
+
+
 # generic hooks to record operations if something changed in a compound tree ###
 
 class AddOrRemoveChildrenHook(hook.Hook):
     """Some relation involved in a compound graph is added or removed."""
     __regid__ = 'compound.graph.updated'
diff --git a/test/unittest_hooks.py b/test/unittest_hooks.py
--- a/test/unittest_hooks.py
+++ b/test/unittest_hooks.py
@@ -100,20 +100,23 @@ class SAEMRefHooksTC(CubicWebTC):
             # edit composite children
             unit_alt_seq.reverse_seda_title[0].cw_set(title=u'archive name')
             cnx.commit()
             self.assertMDNow(transfer)
             self.resetMD(cnx, transfer)
+            self.resetMD(cnx, scheme)
             # edit relation to a composite children
             code = scheme.reverse_in_scheme[0]
             rule_seq = cnx.create_entity('SEDASeqAccessRuleRule',
                                          reverse_seda_start_date=cnx.create_entity('SEDAStartDate'),
                                          seda_rule=code)
             rule = cnx.create_entity('SEDAAccessRule',
                                      seda_access_rule=transfer,
                                      seda_seq_access_rule_rule=rule_seq)
             cnx.commit()
             self.assertMDNow(transfer)
+            # should not have touched scheme's date
+            self.assertEqual(scheme.modification_date, YESTERDAY)
             self.resetMD(cnx, transfer)
             # edit link from composite children to an entity which is not part of the container
             rule_seq.cw_set(seda_rule=None)
             cnx.commit()
             self.assertMDNow(transfer)
@@ -497,10 +500,48 @@ class EntityLifeCycleTC(CubicWebTC):
             concept = scheme.add_concept(u'hello')
             cnx.commit()
             concept.cw_delete()
             cnx.commit()
 
+    def test_inter_containers(self):
+        with self.admin_access.repo_cnx() as cnx:
+            scheme = testutils.scheme_for_type(
+                cnx, 'seda_rule', 'SEDASeqAccessRuleRule', u'AR038')
+            code = scheme.reverse_in_scheme[0]
+            transfer = testutils.setup_profile(cnx)
+            unit, unit_alt, unit_alt_seq = testutils.create_archive_unit(transfer)
+            cnx.commit()
+
+            nb_scheme_activities = len(cnx.find('Activity', used=scheme.eid))
+            nb_concept_activities = len(cnx.find('Activity', used=code.eid))
+            nb_transfer_activities = len(cnx.find('Activity', used=transfer.eid))
+
+            rule_seq = cnx.create_entity(
+                'SEDASeqAccessRuleRule',
+                reverse_seda_start_date=cnx.create_entity('SEDAStartDate'),
+                seda_rule=code)
+            cnx.create_entity(
+                'SEDAAccessRule',
+                seda_access_rule=transfer,
+                seda_seq_access_rule_rule=rule_seq)
+            cnx.commit()
+
+            self.assertEqual(len(cnx.find('Activity', used=code.eid)),
+                             nb_concept_activities)
+            self.assertEqual(len(cnx.find('Activity', used=transfer.eid)),
+                             nb_transfer_activities + 1)
+
+            cnx.create_entity('SEDAMimeTypeCodeListVersion',
+                              seda_mime_type_code_list_version_from=transfer,
+                              seda_mime_type_code_list_version_to=scheme)
+            cnx.commit()
+
+            self.assertEqual(len(cnx.find('Activity', used=scheme.eid)),
+                             nb_scheme_activities)
+            self.assertEqual(len(cnx.find('Activity', used=transfer.eid)),
+                             nb_transfer_activities + 2)
+
 
 class SEDAArchiveTransferHooksTC(CubicWebTC):
 
     def test_profile_deprecated(self):
         """Test hook deprecating a SEDA Profile upon successor publication."""


More information about the saem-devel mailing list