Add validation hook ensuring we don't mark as simplified a profile which can't
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 13 Oct 2016 13:03:10 +0200
changeset 1834 d3e384864e8f
parent 1833 8112742e0b48
child 1835 fa0a0bb2da4b
Add validation hook ensuring we don't mark as simplified a profile which can't A simplified profile hides most of the complexity of a full seda profile. The diagnosis tool indicates if a profile is using some construct which shouldn't occur in a simplified profile. This patch introduce a hook that will forbid to set 'simplified_profile=True' on a profile which isn't compatible, or that we don't do incompatible change on a simplified profile (though this should not occur from the UI).
hooks.py
i18n/en.po
i18n/fr.po
test/test_hooks.py
--- a/hooks.py	Fri Oct 14 11:17:15 2016 +0200
+++ b/hooks.py	Thu Oct 13 13:03:10 2016 +0200
@@ -249,7 +249,12 @@
         with cnx.deny_all_hooks_but():
             for profile in profiles:
                 adapter = profile.cw_adapt_to('ISEDACompatAnalyzer')
-                profile.cw_set(compat_list=u', '.join(sorted(adapter.diagnose())))
+                supported_formats = adapter.diagnose()
+                profile.cw_set(compat_list=u', '.join(sorted(supported_formats)))
+                if profile.simplified_profile and 'simplified' not in supported_formats:
+                    raise ValidationError(
+                        profile.eid, {'': _("This profile can't be turned to simplified. "
+                                            "See the diagnostic tab for more information")})
 
     def add_entity(self, entity):
         """Add entity, its parent entities (up to the container root) for update of their
@@ -299,6 +304,27 @@
         op.add_entity(self._cw.entity_from_eid(self.eidto))
 
 
+WATCH_ETYPES = defaultdict(set)
+for rule in diag.RULES.values():
+    for etype_attr in rule.watch:
+        if isinstance(etype_attr, tuple):
+            WATCH_ETYPES[etype_attr[0]].add(etype_attr[1])
+
+WATCH_ETYPES['SEDAArchiveTransfer'].add('simplified_profile')
+
+
+class UpdateWatchedProfileElementHook(hook.Hook):
+    """Some entity involved in diagnosis of the profile is created or updated."""
+    __regid__ = 'seda.transfer.updated.checkcompat'
+    __select__ = hook.Hook.__select__ & is_instance(*WATCH_ETYPES)
+    events = ('before_add_entity', 'before_update_entity')
+    category = 'metadata'
+
+    def __call__(self):
+        if WATCH_ETYPES[self.entity.cw_etype] & set(self.entity.cw_edited):
+            CheckProfileSEDACompatiblityOp.get_instance(self._cw).add_entity(self.entity)
+
+
 def registration_callback(vreg):
     from cubicweb.server import ON_COMMIT_ADD_RELATIONS
     from cubes.seda import seda_profile_container_def, iter_all_rdefs
--- a/i18n/en.po	Fri Oct 14 11:17:15 2016 +0200
+++ b/i18n/en.po	Thu Oct 13 13:03:10 2016 +0200
@@ -2726,6 +2726,11 @@
 msgid "This object is used as a relationship target of the following entities"
 msgstr ""
 
+msgid ""
+"This profile can't be turned to simplified. See the diagnostic tab for more "
+"information"
+msgstr ""
+
 msgid "XSD content type"
 msgstr ""
 
--- a/i18n/fr.po	Fri Oct 14 11:17:15 2016 +0200
+++ b/i18n/fr.po	Thu Oct 13 13:03:10 2016 +0200
@@ -2732,6 +2732,13 @@
 msgid "This object is used as a relationship target of the following entities"
 msgstr "Cet objet est utilisé comme cible des relations suivantes :"
 
+msgid ""
+"This profile can't be turned to simplified. See the diagnostic tab for more "
+"information"
+msgstr ""
+"Ce profil ne peut être transformé en un profil simplifié. Regardez l'onglet "
+"\"diagnostique\" pour plus d'information"
+
 msgid "XSD content type"
 msgstr "type de contenu"
 
--- a/test/test_hooks.py	Fri Oct 14 11:17:15 2016 +0200
+++ b/test/test_hooks.py	Thu Oct 13 13:03:10 2016 +0200
@@ -195,6 +195,35 @@
             self.assertTrue(transfer.reverse_seda_appraisal_rule_code_list_version_from)
 
 
+class CheckProfileTC(CubicWebTC):
+
+    def test_base(self):
+        with self.admin_access.repo_cnx() as cnx:
+            transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'diagnosis testing')
+            unit, unit_alt, unit_alt_seq = create_archive_unit(transfer)
+            access_rule = cnx.create_entity('SEDAAccessRule', seda_access_rule=unit_alt_seq)
+            cnx.commit()
+
+            with self.assertRaises(ValidationError):
+                transfer.cw_set(simplified_profile=True)
+                cnx.commit()
+
+            access_rule_seq = cnx.create_entity('SEDASeqAccessRuleRule',
+                                                reverse_seda_seq_access_rule_rule=access_rule)
+            start_date = cnx.create_entity('SEDAStartDate',
+                                           seda_start_date=access_rule_seq)
+            transfer.cw_set(simplified_profile=True)
+            cnx.commit()
+
+            with self.assertRaises(ValidationError):
+                start_date.cw_set(user_cardinality=u'0..1')
+                cnx.commit()
+
+            with self.assertRaises(ValidationError):
+                access_rule_seq.cw_delete()
+                cnx.commit()
+
+
 if __name__ == '__main__':
     import unittest
     unittest.main()