Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/okfn/ckan
Browse files Browse the repository at this point in the history
  • Loading branch information
rossjones committed Apr 30, 2012
2 parents b9bd40e + 010066d commit b1d529f
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 33 deletions.
4 changes: 2 additions & 2 deletions ckan/lib/helpers.py
Expand Up @@ -676,8 +676,8 @@ def group_link(group):
url = url_for(controller='group', action='read', id=group['name'])
return link_to(group['name'], url)

def dump_json(obj):
return json.dumps(obj)
def dump_json(obj, **kw):
return json.dumps(obj, **kw)

def auto_log_message(*args):
# auto_log_message() used to need c passing as the first arg
Expand Down
20 changes: 14 additions & 6 deletions ckan/plugins/core.py
Expand Up @@ -6,11 +6,10 @@
from inspect import isclass
from itertools import chain
from pkg_resources import iter_entry_points
from pyutilib.component.core import PluginGlobals, ExtensionPoint as PluginImplementations, implements
from pyutilib.component.core import PluginGlobals, implements
from pyutilib.component.core import ExtensionPoint as PluginImplementations
from pyutilib.component.core import SingletonPlugin as _pca_SingletonPlugin
from pyutilib.component.core import Plugin as _pca_Plugin
from pyutilib.component.core import PluginEnvironment
from sqlalchemy.orm.interfaces import MapperExtension

from ckan.plugins.interfaces import IPluginObserver

Expand All @@ -23,18 +22,20 @@

log = logging.getLogger(__name__)

# Entry point group.
# Entry point group.
PLUGINS_ENTRY_POINT_GROUP = "ckan.plugins"

# Entry point group for system plugins (those that are part of core ckan and do
# not need to be explicitly enabled by the user)
SYSTEM_PLUGINS_ENTRY_POINT_GROUP = "ckan.system_plugins"


class PluginNotFoundException(Exception):
"""
Raised when a requested plugin cannot be found.
"""


class Plugin(_pca_Plugin):
"""
Base class for plugins which require multiple instances.
Expand All @@ -43,6 +44,7 @@ class Plugin(_pca_Plugin):
probably use SingletonPlugin.
"""


class SingletonPlugin(_pca_SingletonPlugin):
"""
Base class for plugins which are singletons (ie most of them)
Expand All @@ -52,6 +54,7 @@ class SingletonPlugin(_pca_SingletonPlugin):
same singleton instance.
"""


def _get_service(plugin):
"""
Return a service (ie an instance of a plugin class).
Expand Down Expand Up @@ -100,13 +103,15 @@ def load_all(config):
for plugin in plugins:
load(plugin)


def reset():
"""
Clear and reload all configured plugins
"""
from pylons import config
load_all(config)


def load(plugin):
"""
Load a single plugin, given a plugin name, class or instance
Expand All @@ -120,6 +125,7 @@ def load(plugin):
observer_plugin.after_load(service)
return service


def unload_all():
"""
Unload (deactivate) all loaded plugins
Expand All @@ -128,6 +134,7 @@ def unload_all():
for service in env.services.copy():
unload(service)


def unload(plugin):
"""
Unload a single plugin, given a plugin name, class or instance
Expand All @@ -144,6 +151,7 @@ def unload(plugin):

return service


def find_user_plugins(config):
"""
Return all plugins specified by the user in the 'ckan.plugins' config
Expand All @@ -159,15 +167,15 @@ def find_user_plugins(config):
plugins.extend(ep.load() for ep in entry_points)
return plugins


def find_system_plugins():
"""
Return all plugins in the ckan.system_plugins entry point group.
These are essential for operation and therefore cannot be enabled/disabled
through the configuration file.
"""
return (
ep.load()
for ep in iter_entry_points(group=SYSTEM_PLUGINS_ENTRY_POINT_GROUP)
)

43 changes: 29 additions & 14 deletions ckan/plugins/interfaces.py
Expand Up @@ -21,6 +21,7 @@
from inspect import isclass
from pyutilib.component.core import Interface as _pca_Interface


class Interface(_pca_Interface):

@classmethod
Expand Down Expand Up @@ -80,13 +81,15 @@ def before_map(self, map):

def after_map(self, map):
"""
Called after routes map is set up. ``after_map`` can be used to add fall-back handlers.
Called after routes map is set up. ``after_map`` can be used to
add fall-back handlers.
:param map: Routes map object
:returns: Modified version of the map object
"""
return map


class IMapper(Interface):
"""
A subset of the SQLAlchemy mapper extension hooks.
Expand All @@ -104,7 +107,8 @@ class IMapper(Interface):

def before_insert(self, mapper, connection, instance):
"""
Receive an object instance before that instance is INSERTed into its table.
Receive an object instance before that instance is INSERTed into
its table.
"""

def before_update(self, mapper, connection, instance):
Expand Down Expand Up @@ -132,6 +136,7 @@ def after_delete(self, mapper, connection, instance):
Receive an object instance after that instance is DELETEed.
"""


class ISession(Interface):
"""
A subset of the SQLAlchemy session extension hooks.
Expand Down Expand Up @@ -167,6 +172,7 @@ def after_rollback(self, session):
Execute after a rollback has occured.
"""


class IDomainObjectModification(Interface):
"""
Receives notification of new, changed and deleted datesets.
Expand All @@ -175,6 +181,7 @@ class IDomainObjectModification(Interface):
def notify(self, entity, operation):
pass


class IResourceUrlChange(Interface):
"""
Receives notification of changed urls.
Expand All @@ -183,6 +190,7 @@ class IResourceUrlChange(Interface):
def notify(self, resource):
pass


class ITagController(Interface):
'''
Hook into the Tag controller. These will usually be called just before
Expand All @@ -198,6 +206,7 @@ def before_view(self, tag_dict):
'''
return tag_dict


class IGroupController(Interface):
"""
Hook into the Group controller. These will
Expand Down Expand Up @@ -226,11 +235,13 @@ def delete(self, entity):

def before_view(self, pkg_dict):
'''
Extensions will recieve this before the group gets displayed. The dictionary
passed will be the one that gets sent to the template.
Extensions will recieve this before the group gets
displayed. The dictionary passed will be the one that gets
sent to the template.
'''
return pkg_dict


class IPackageController(Interface):
"""
Hook into the package controller.
Expand Down Expand Up @@ -288,17 +299,19 @@ def after_search(self, search_results, search_params):

def before_index(self, pkg_dict):
'''
Extensions will receive what will be given to the solr for indexing.
This is essentially a flattened dict (except for multlivlaued fields such as tags
of all the terms sent to the indexer. The extension can modify this by returning
an altered version.
Extensions will receive what will be given to the solr for
indexing. This is essentially a flattened dict (except for
multli-valued fields such as tags) of all the terms sent to
the indexer. The extension can modify this by returning an
altered version.
'''
return pkg_dict

def before_view(self, pkg_dict):
'''
Extensions will recieve this before the dataset gets displayed. The dictionary
passed will be the one that gets sent to the template.
Extensions will recieve this before the dataset gets
displayed. The dictionary passed will be the one that gets
sent to the template.
'''
return pkg_dict

Expand Down Expand Up @@ -332,6 +345,7 @@ def after_unload(self, service):
This method is passed the instantiated service object.
"""


class IConfigurable(Interface):
"""
Pass configuration to plugins and extensions
Expand All @@ -342,6 +356,7 @@ def configure(self, config):
Called by load_environment
"""


class IConfigurer(Interface):
"""
Configure CKAN (pylons) environment via the ``pylons.config`` object
Expand Down Expand Up @@ -382,6 +397,7 @@ def is_authorized(self, username, action, domain_obj):
other Authorizers to run; True will shortcircuit and return.
"""


class IActions(Interface):
"""
Allow adding of actions to the logic layer.
Expand All @@ -392,6 +408,7 @@ def get_actions(self):
function and the values being the functions themselves.
"""


class IAuthFunctions(Interface):
"""
Allow customisation of default Authorization implementation
Expand All @@ -402,6 +419,7 @@ def get_auth_functions(self):
implementation overrides
"""


class ITemplateHelpers(Interface):
"""
Allow adding extra template functions available via h variable
Expand All @@ -412,6 +430,7 @@ def get_helpers(self):
function and the values being the functions themselves.
"""


class IDatasetForm(Interface):
"""
Allows customisation of the package controller as a plugin.
Expand Down Expand Up @@ -499,7 +518,6 @@ def history_template(self):
rendered for the history page
"""


def package_form(self):
"""
Returns a string representing the location of the template to be
Expand Down Expand Up @@ -616,8 +634,6 @@ def history_template(self):
rendered for the history page
"""



def package_form(self):
"""
Returns a string representing the location of the template to be
Expand Down Expand Up @@ -649,4 +665,3 @@ def setup_template_variables(self, context, data_dict):
"""

##### End of hooks #####

11 changes: 7 additions & 4 deletions ckan/plugins/toolkit.py
Expand Up @@ -8,10 +8,12 @@

__all__ = ['toolkit']


class CkanVersionException(Exception):
''' Exception raised if required ckan version is not available. '''
pass


class _Toolkit(object):
'''This class is intended to make functions/objects consistently
available to plugins, whilst giving developers the ability move
Expand Down Expand Up @@ -40,7 +42,8 @@ class _Toolkit(object):
'literal', # stop tags in a string being escaped
'get_action', # get logic action function
'check_access', # check logic function authorisation
'ObjectNotFound', # action not found exception (ckan.logic.NotFound)
'ObjectNotFound', # action not found exception
# (ckan.logic.NotFound)
'NotAuthorized', # action not authorized exception
'ValidationError', # model update validation error
'CkanCommand', # class for providing cli interfaces
Expand All @@ -53,7 +56,6 @@ class _Toolkit(object):
'CkanVersionException',
]


def __init__(self):
self._toolkit = {}

Expand Down Expand Up @@ -85,7 +87,7 @@ def _initialize(self):

t['get_action'] = logic.get_action
t['check_access'] = logic.check_access
t['ObjectNotFound'] = logic.NotFound ## Name change intentional
t['ObjectNotFound'] = logic.NotFound # Name change intentional
t['NotAuthorized'] = logic.NotAuthorized
t['ValidationError'] = logic.ValidationError

Expand Down Expand Up @@ -117,7 +119,8 @@ def _render_snippet(cls, template, data=None):
def _add_template_directory(cls, config, relative_path):
''' Function to aid adding extra template paths to the config.
The path is relative to the file calling this function. '''
cls._add_served_directory(config, relative_path, 'extra_template_paths')
cls._add_served_directory(config, relative_path,
'extra_template_paths')

@classmethod
def _add_public_directory(cls, config, relative_path):
Expand Down
8 changes: 4 additions & 4 deletions ckan/templates/facets.html
Expand Up @@ -5,7 +5,7 @@
py:strip=""
>

<!--
<!--!
Construct a facet <div> populated with links to filtered results.
name
Expand Down Expand Up @@ -40,7 +40,7 @@ <h2>${h.facet_title(title)}</h2>
</div>
</py:def>

<!--
<!--!
Generate <li>s for facet items. The generated tags are not wrapped by any
other tag, ie - it's up to the caller to wrap them in something suitable.
Expand Down Expand Up @@ -75,7 +75,7 @@ <h2>${h.facet_title(title)}</h2>
</li>
</py:def>

<!--
<!--!
DEPRECATED. Provided only for backward compatibility with existing plugins.
Use `facet_div` instead.
Expand Down Expand Up @@ -129,7 +129,7 @@ <h2>${title(code)}</h2>
</div>
</py:def>

<!--
<!--!
DEPRECATED. Provided only for backward compatibility with existing plugins.
Use `facet_li` instead.
Expand Down

0 comments on commit b1d529f

Please sign in to comment.