[hooks] Prevent ckanpublish hooks from being ran upon setting of CKAN identifier attributes on dataset/resource
authorDenis Laxalde <denis.laxalde@logilab.fr>
Wed, 21 Jan 2015 16:47:14 +0100
changeset 66 e9f30ed9b309
parent 59 1c5b5774bec7
child 67 64966fde037f
[hooks] Prevent ckanpublish hooks from being ran upon setting of CKAN identifier attributes on dataset/resource This avoids those hooks to be called "recursively" as this sometimes causes unexpected behaviors. As a result, compute the modification_date before the ckan_resource_id attribute is set in tests so that CKAN last_modified attribute still matches with this date. Closes #4869936.
hooks.py
test/unittest_hooks.py
--- a/hooks.py	Wed Jan 21 14:09:10 2015 +0100
+++ b/hooks.py	Wed Jan 21 16:47:14 2015 +0100
@@ -81,6 +81,7 @@
                   adaptable('ICKANDataset') &
                   score_entity(lambda x: x.ckan_dataset_id))
     events = ('before_delete_entity', )
+    category = 'ckanpublish.dataset'
 
     def __call__(self):
         CKANDatasetOp.get_instance(self._cw).add_data(self.entity.eid)
@@ -92,6 +93,7 @@
     __select__ = (hook.Hook.__select__ & ckan_instance_configured &
                   adaptable('ICKANDataset'))
     events = ('after_add_entity', 'after_update_entity', )
+    category = 'ckanpublish.dataset'
 
     def __call__(self):
         CKANDatasetOp.get_instance(self._cw).add_data(self.entity.eid)
@@ -117,9 +119,10 @@
                               data.keys(), datasetid)
                 else:
                     datasetid = create_dataset(config, eid, data)
-                    self.cnx.execute(
-                        'SET X ckan_dataset_id %(dsid)s WHERE X eid %(eid)s',
-                        {'eid': eid, 'dsid': datasetid})
+                    with self.cnx.allow_all_hooks_but('ckanpublish.dataset'):
+                        self.cnx.execute(
+                            'SET X ckan_dataset_id %(dsid)s WHERE X eid %(eid)s',
+                            {'eid': eid, 'dsid': datasetid})
                     self.info('created CKAN dataset %s', datasetid)
 
 
@@ -129,6 +132,7 @@
     __select__ = (hook.Hook.__select__ & ckan_instance_configured &
                   adaptable('ICKANResource') &
                   score_entity(lambda x: x.ckan_resource_id))
+    category = 'ckanpublish.resource'
     events = ('before_delete_entity', )
 
     def __call__(self):
@@ -160,6 +164,7 @@
     __select__ = (hook.Hook.__select__ & ckan_instance_configured &
                   partial_match_rtype())
     __abstract__ = True
+    category = 'ckanpublish.resource'
     events = ('after_add_relation', )
     rtype = None  # Use to fill the `expected` argument of match_rtype.
     role  = 'object'
@@ -176,6 +181,7 @@
     __regid__ = 'ckanpublish.update-ckan-resource'
     __select__ = (hook.Hook.__select__ & ckan_instance_configured &
                   adaptable('ICKANResource'))
+    category = 'ckanpublish.resource'
     events = ('after_update_entity', )
 
     def __call__(self):
@@ -206,9 +212,10 @@
                         continue
                     resourceid = create_dataset_resource(
                         config, eid, dataset.ckan_dataset_id, metadata, data)
-                    self.cnx.execute(
-                        'SET X ckan_resource_id %(rid)s WHERE X eid %(eid)s',
-                        {'eid': eid, 'rid': resourceid})
+                    with self.cnx.allow_all_hooks_but('ckanpublish.resource'):
+                        self.cnx.execute(
+                            'SET X ckan_resource_id %(rid)s WHERE X eid %(eid)s',
+                            {'eid': eid, 'rid': resourceid})
                     self.info('added resource %s', resourceid)
                 else:
                     update_dataset_resource(
--- a/test/unittest_hooks.py	Wed Jan 21 14:09:10 2015 +0100
+++ b/test/unittest_hooks.py	Wed Jan 21 16:47:14 2015 +0100
@@ -80,6 +80,10 @@
 
     def _check_resource_creation(self, cnx, dataset, resource):
         self.set_description('resource creation')
+        # Keep the modification_date before update of the File due to setting
+        # the ckan_resource_id attribute as this event will not be propagated
+        # to CKAN instance since the corresponding hook is disabled.
+        resource_md = resource.modification_date.isoformat()
         dataset.cw_set(resources=resource)
         cnx.commit()
         resource.cw_clear_all_caches()
@@ -92,8 +96,7 @@
                            {'id': resource.ckan_resource_id})
         self.assertEqual(result['created'],
                          resource.creation_date.isoformat())
-        self.assertEqual(result['last_modified'],
-                         resource.modification_date.isoformat())
+        self.assertEqual(result['last_modified'], resource_md)
         self.assertEqual(result['name'], u'blurp')
         self.assertEqual(result['mimetype'], 'text/plain')