Commit 218f684e authored by Denis Laxalde's avatar Denis Laxalde
Browse files

[hooks] Trigger CKAN resource creation upon addition of the link to dataset relation

Related to #4753964.
parent 681487d37369
......@@ -18,4 +18,9 @@ dedicated attributes on the entities:
* ``ICKANResource`` adapter relies on a ``ckan_resource_id`` attribute. It
is used to related some CubicWeb entity type to a CKAN resource.
The push of a resource on CKAN instance should be triggered by the
addition of a relation between the dataset-like entity and a resource-like
entity in CubicWeb. This is handled by the `LinkResourceToDatasetHook` hook,
which is abstract and should thus subclass by setting its `rtype` attribute.
See ``test/data`` for a minimal example.
......@@ -18,8 +18,8 @@
from requests.exceptions import RequestException
from cubicweb import ValidationError
from cubicweb.predicates import adaptable, score_entity
from cubicweb import ValidationError, role
from cubicweb.predicates import adaptable, score_entity, PartialPredicateMixIn
from cubicweb.server import hook
from cubes.ckanpublish.utils import (ckan_post, CKANPostError,
......@@ -135,12 +135,48 @@ class DeleteCKANResourceHook(hook.Hook):
CKANResourceOp.get_instance(self._cw).add_data(self.entity.eid)
class AddOrUpdateCKANResourceHook(hook.Hook):
"""Add or update a CKAN resource upon addition or update of an entity"""
__regid__ = 'ckanpublish.add-update-ckan-resource'
class partial_match_rtype(PartialPredicateMixIn, hook.match_rtype):
"""Same as :class:~`cubicweb.server.hook.match_rtype`, but will look for
attributes `rtype`, `role`, `frometypes` and `toetypes` on the selected
class to get information which is otherwise expected by the initializer.
"""
def __init__(self, *expected, **more):
super(partial_match_rtype, self).__init__()
def complete(self, cls):
self.expected = (cls.rtype, )
self.role = role(cls)
self.frometypes = getattr(cls, 'frometypes', None)
self.toetypes = getattr(cls, 'toetypes', None)
class LinkResourceToDatasetHook(hook.Hook):
"""Create a CKAN dataset upon link of a resource-like entity to a
dataset-like entity.
Actual implementations should at least fill the `rtype` attribute.
"""
__regid__ = 'ckanpublish.link-ckan-resource-to-ckan-dataset'
__select__ = (hook.Hook.__select__ & ckan_instance_configured &
partial_match_rtype())
__abstract__ = True
events = ('after_add_relation', )
rtype = None # Use to fill the `expected` argument of match_rtype.
role = 'object'
frometypes = None
toetypes = None
def __call__(self):
eid = {'subject': self.eidfrom, 'object': self.eidto}[self.role]
CKANResourceOp.get_instance(self._cw).add_data(eid)
class UpdateCKANResourceHook(hook.Hook):
"""Update a CKAN resource upon update of an resource-like entity"""
__regid__ = 'ckanpublish.update-ckan-resource'
__select__ = (hook.Hook.__select__ & ckan_instance_configured &
adaptable('ICKANResource'))
events = ('after_add_entity', 'after_update_entity', )
events = ('after_update_entity', )
def __call__(self):
CKANResourceOp.get_instance(self._cw).add_data(self.entity.eid)
......
from cubicweb.server import hook
from cubes.ckanpublish.hooks import CKANDatasetOp
from cubes.ckanpublish.hooks import CKANDatasetOp, LinkResourceToDatasetHook
class AddUpdateMaintainerHook(hook.Hook):
......@@ -13,11 +13,10 @@ class AddUpdateMaintainerHook(hook.Hook):
CKANDatasetOp.get_instance(self._cw).add_data(self.eidfrom)
class AddDeleteFileResourceHook(hook.Hook):
__regid__ = 'ckanpublish-tests.add-delete-file-resource'
__select__ = (hook.Hook.__select__ &
hook.match_rtype('resources', frometypes=('CWDataSet')))
events = ('after_add_relation', 'after_delete_relation')
def __call__(self):
CKANDatasetOp.get_instance(self._cw).add_data(self.eidfrom)
class MyLinkResourceToDatasetHook(LinkResourceToDatasetHook):
"""Implementation of `resource` relation hook."""
rtype = 'resources'
role = 'object'
# frometypes/toetypes are not actually required.
frometypes = 'CWDataSet'
toetypes = 'File'
......@@ -90,8 +90,7 @@ class CKANPublishHooksTC(CubicWebTC):
description=u'flop')
resource = cnx.create_entity('File', data=Binary('yui'),
data_format=u'text/plain',
data_name=u'blurp',
reverse_resources=dataset)
data_name=u'blurp')
cnx.commit()
yield self._check_resource_creation, cnx, dataset, resource
yield self._check_resource_update, cnx, resource
......@@ -99,6 +98,9 @@ class CKANPublishHooksTC(CubicWebTC):
def _check_resource_creation(self, cnx, dataset, resource):
self.set_description('resource creation')
dataset.cw_set(resources=resource)
cnx.commit()
resource.cw_clear_all_caches()
self.assertIsNotNone(resource.ckan_resource_id)
result = ckan_post(self.ckan_config, 'package_show',
{'id': dataset.ckan_dataset_id})
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment