Skip to content

Commit

Permalink
Merge pull request #5112 from mutantsan/5108-allow-extensions-define-…
Browse files Browse the repository at this point in the history
…click-cmds

[#5108] Allow extensions to define Click commands
  • Loading branch information
smotornyuk committed Dec 13, 2019
2 parents c0ee5f5 + 8e12807 commit 06af539
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
18 changes: 17 additions & 1 deletion ckan/cli/cli.py
Expand Up @@ -2,6 +2,7 @@

import logging

import ckan.plugins as p
import click
from ckan.cli import config_tool
from ckan.cli import (
Expand Down Expand Up @@ -31,19 +32,34 @@
log = logging.getLogger(__name__)


class CustomGroup(click.Group):
def get_command(self, ctx, name):
cmd = super(CustomGroup, self).get_command(ctx, name)
if not cmd:
self.invoke(ctx)
cmd = super(CustomGroup, self).get_command(ctx, name)
return cmd


class CkanCommand(object):

def __init__(self, conf=None):
self.config = load_config(conf)
self.app = make_app(self.config.global_conf, **self.config.local_conf)


@click.group()
@click.group(
invoke_without_command=True,
cls=CustomGroup
)
@click.help_option(u'-h', u'--help')
@click_config_option
@click.pass_context
def ckan(ctx, config, *args, **kwargs):
ctx.obj = CkanCommand(config)
for plugin in p.PluginImplementations(p.IClick):
for cmd in plugin.get_commands():
ckan.add_command(cmd)


ckan.add_command(jobs.jobs)
Expand Down
15 changes: 15 additions & 0 deletions ckan/plugins/interfaces.py
Expand Up @@ -39,6 +39,7 @@
u'IBlueprint',
u'IPermissionLabels',
u'IForkObserver',
u'IClick',
]


Expand Down Expand Up @@ -1779,3 +1780,17 @@ def before_fork(self):
u'''
Called shortly before the CKAN process is forked.
'''


class IClick(Interface):
u'''
Allow extensions to define click commands.
'''
def get_commands(self):
u'''
Return a list of command functions objects
to be registered by the click.add_command.
:returns: command functions objects
:rtype: list of function objects
'''
12 changes: 8 additions & 4 deletions ckan/plugins/toolkit.py
Expand Up @@ -76,6 +76,8 @@ class _Toolkit(object):
'CkanCommand',
# function for initializing CLI interfaces
'load_config',
# function to promt the exception in CLI command
'error_shout',
# base class for IDatasetForm plugins
'DefaultDatasetForm',
# base class for IGroupForm plugins
Expand Down Expand Up @@ -138,6 +140,7 @@ def _initialize(self):
import ckan.logic.validators as logic_validators
import ckan.lib.navl.dictization_functions as dictization_functions
import ckan.lib.helpers as h
import ckan.cli as cli
import ckan.lib.plugins as lib_plugins
import ckan.common as common
from ckan.exceptions import (
Expand All @@ -148,7 +151,7 @@ def _initialize(self):

import ckan.common as converters
if six.PY2:
import ckan.lib.cli as cli
import ckan.lib.cli as old_cli
import pylons

# Allow class access to these modules
Expand Down Expand Up @@ -251,11 +254,12 @@ def _initialize(self):
t['StopOnError'] = dictization_functions.StopOnError
t['UnknownValidator'] = logic.UnknownValidator
t['Invalid'] = logic_validators.Invalid

t['DefaultDatasetForm'] = lib_plugins.DefaultDatasetForm
t['DefaultGroupForm'] = lib_plugins.DefaultGroupForm
t['DefaultOrganizationForm'] = lib_plugins.DefaultOrganizationForm

t['error_shout'] = cli.error_shout

t['redirect_to'] = h.redirect_to
t['url_for'] = h.url_for
t['get_or_bust'] = logic.get_or_bust
Expand Down Expand Up @@ -291,8 +295,8 @@ def _initialize(self):
'''
t['BaseController'] = base.BaseController
# TODO: Sort these out
t['CkanCommand'] = cli.CkanCommand
t['load_config'] = cli.load_config
t['CkanCommand'] = old_cli.CkanCommand
t['load_config'] = old_cli.load_config

# check contents list correct
errors = set(t).symmetric_difference(set(self.contents))
Expand Down

0 comments on commit 06af539

Please sign in to comment.