[ckan-changes] commit/ckan: kindly: [logic] new way to get actions and plugin to override them

Bitbucket commits-noreply at bitbucket.org
Thu Jul 21 00:01:32 UTC 2011


1 new changeset in ckan:

http://bitbucket.org/okfn/ckan/changeset/36905a4b5d8b/
changeset:   36905a4b5d8b
branch:      feature-1211-drupal
user:        kindly
date:        2011-07-21 02:01:07
summary:     [logic] new way to get actions and plugin to override them
affected #:  4 files (2.6 KB)

--- a/ckan/controllers/api.py	Tue Jul 19 12:57:39 2011 +0100
+++ b/ckan/controllers/api.py	Thu Jul 21 01:01:07 2011 +0100
@@ -11,6 +11,7 @@
 from ckan.plugins import PluginImplementations, IGroupController
 from ckan.lib.munge import munge_title_to_name
 from ckan.lib.navl.dictization_functions import DataError
+from ckan.logic import get_action
 import ckan.logic.action.get as get 
 import ckan.logic.action.create as create
 import ckan.logic.action.update as update
@@ -129,32 +130,9 @@
         response_data = {}
         response_data['version'] = ver or '1'
         return self._finish_ok(response_data) 
-
-    @classmethod
-    def create_actions(cls):
-        if cls._actions:
-            return 
-        for name, action in get.__dict__.iteritems():
-            if not name.startswith('_') and callable(action):
-                cls._actions[name] = action
-        for name, action in update.__dict__.iteritems():
-            if not name.startswith('_') and callable(action):
-                cls._actions[name] = action
-        for name, action in create.__dict__.iteritems():
-            if not name.startswith('_') and callable(action):
-                cls._actions[name] = action
-
-    def get_action(self, action):
-        self.create_actions()
-        return self._actions[action]
-
-    @classmethod
-    def register_action(cls, name, function):
-        cls.create_actions()
-        cls._actions[name] = function
     
     def action(self, logic_function):
-        function = self.get_action(logic_function)
+        function = get_action(logic_function)
         
         context = {'model': model, 'session': model.Session, 'user': c.user}
         model.Session()._context = context
@@ -254,10 +232,10 @@
     def create(self, ver=None, register=None, subregister=None, id=None, id2=None):
 
         action_map = {
-            ('package', 'relationships'): create.package_relationship_create,
-             'group': create.group_create_rest,
-             'package': create.package_create_rest,
-             'rating': create.rating_create,
+            ('package', 'relationships'): get_action('package_relationship_create'),
+             'group': get_action('group_create_rest'),
+             'package': get_action('package_create_rest'),
+             'rating': get_action('rating_create'),
         }
 
         for type in model.PackageRelationship.get_all_types():
@@ -304,9 +282,9 @@
     def update(self, ver=None, register=None, subregister=None, id=None, id2=None):
 
         action_map = {
-            ('package', 'relationships'): update.package_relationship_update,
-             'package': update.package_update_rest,
-             'group': update.group_update_rest,
+            ('package', 'relationships'): get_action('package_relationship_update'),
+             'package': get_action('package_update_rest'),
+             'group': get_action('group_update_rest'),
         }
         for type in model.PackageRelationship.get_all_types():
             action_map[('package', type)] = update.package_relationship_update


--- a/ckan/controllers/package.py	Tue Jul 19 12:57:39 2011 +0100
+++ b/ckan/controllers/package.py	Thu Jul 21 01:01:07 2011 +0100
@@ -16,6 +16,7 @@
 import ckan.logic.action.create as create
 import ckan.logic.action.update as update
 import ckan.logic.action.get as get
+from ckan.logic import get_action
 from ckan.logic.schema import package_form_schema
 from ckan.lib.base import request, c, BaseController, model, abort, h, g, render
 from ckan.lib.base import etag_cache, response, redirect, gettext
@@ -414,7 +415,7 @@
                 tuplize_dict(parse_params(request.POST))))
             self._check_data_dict(data_dict)
             context['message'] = data_dict.get('log_message', '')
-            pkg = create.package_create(context, data_dict)
+            pkg = get_action('package_create')(context, data_dict)
 
             if context['preview']:
                 PackageSaver().render_package(pkg, context)
@@ -445,7 +446,7 @@
             if not context['moderated']:
                 context['pending'] = False
             data_dict['id'] = id
-            pkg = update.package_update(context, data_dict)
+            pkg = get_action('package_update')(context, data_dict)
             if request.params.get('save', '') == 'Approve':
                 update.make_latest_pending_package_active(context, data_dict)
             c.pkg = context['package']


--- a/ckan/logic/__init__.py	Tue Jul 19 12:57:39 2011 +0100
+++ b/ckan/logic/__init__.py	Thu Jul 21 01:01:07 2011 +0100
@@ -1,6 +1,8 @@
 import logging
 import ckan.authz
 from ckan.lib.navl.dictization_functions import flatten_dict
+from ckan.plugins import PluginImplementations
+from ckan.plugins.interfaces import IActions
 
 class ActionError(Exception):
     def __init__(self, extra_msg=None):
@@ -90,4 +92,42 @@
         log.debug("No valid API key provided.")
         raise NotAuthorized
     log.debug("Access OK.")
-    return True                
+    return True             
+
+_actions = {}
+
+def get_action(action):
+    if _actions:
+        return _actions.get(action)
+    # Otherwise look in all the plugins to resolve all possible
+    # First get the default ones in the ckan/logic/action directory
+    # Rather than writing them out in full will use __import__
+    # to load anything from ckan.logic.action that looks like it might
+    # be an action 
+    for action_module_name in ['get', 'create', 'update']:
+        module_path = 'ckan.logic.action.'+action_module_name
+        module = __import__(module_path)
+        for part in module_path.split('.')[1:]:
+            module = getattr(module, part)
+        for k, v in module.__dict__.items():
+            if not k.startswith('_'):
+                _actions[k] = v
+    # Then overwrite them with any specific ones in the plugins:
+    resolved_action_plugins = {}
+    fetched_actions = {}
+    for plugin in PluginImplementations(IActions):
+        for name, auth_function in plugin.get_actions().items():
+            if name in resolved_action_plugins:
+                raise Exception(
+                    'The action %r is already implemented in %r' % (
+                        name,
+                        resolved_action_plugins[name]
+                    )
+                )
+            log.debug('Auth function %r was inserted', plugin.name)
+            resolved_action_plugins[name] = plugin.name
+            fetched_actions[name] = auth_function
+    # Use the updated ones in preference to the originals.
+    _actions.update(fetched_actions)
+    return _actions.get(action)
+


--- a/ckan/plugins/interfaces.py	Tue Jul 19 12:57:39 2011 +0100
+++ b/ckan/plugins/interfaces.py	Thu Jul 21 01:01:07 2011 +0100
@@ -300,4 +300,12 @@
         other Authorizers to run; True will shortcircuit and return.
         """
         
-
+class IActions(Interface):
+    """
+    Allow adding of actions to the logic layer.
+    """
+    def get_actions(self):
+        """
+        Should return a dict, the keys being the name of the logic 
+        function and the values being the functions themselves.
+        """

Repository URL: https://bitbucket.org/okfn/ckan/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.




More information about the ckan-changes mailing list