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):
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__ = ''
__select__ = (hook.Hook.__select__ & ckan_instance_configured &
__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]
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 &
events = ('after_add_entity', 'after_update_entity', )
events = ('after_update_entity', )
def __call__(self):
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):
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):
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):
resource = cnx.create_entity('File', data=Binary('yui'),
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')
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