Extend cli commands with plugins

Added a search for plugins modules that contains a `def get_commands()` that returns a clic.Command object. This object is merged with others commands to populate the cli.

An example file that should be placed at `~/.piku/plugins/postgres/__init__.py`

```
import click

@click.group()
def postgres():
    """Postgres command plugin"""
    pass

@postgres.command("postgres:create")
@click.argument('name')
@click.argument('user')
@click.argument('password')
def postgres_create():
    """Postgres create a database"""
    pass

@postgres.command("postgres:drop")
@click.argument('name')
def postgres_drop():
    """Postgres drops a database"""
    pass

@postgres.command("postgres:import")
@click.argument('name')
def postgres_drop():
    """Postgres import a database"""
    pass

@postgres.command("postgres:dump")
@click.argument('name')
def postgres_drop():
    """Postgres dumps a database SQL"""
    pass

def cli_commands():
    return postgres
```
pull/129/head
Jorge Senín 2019-11-17 03:38:33 +01:00
rodzic 666f871bc9
commit 93d291887a
1 zmienionych plików z 22 dodań i 3 usunięć

25
piku.py
Wyświetl plik

@ -8,7 +8,8 @@ try:
except AssertionError: except AssertionError:
exit("Piku requires Python 3.5 or above") exit("Piku requires Python 3.5 or above")
from click import argument, command, group, get_current_context, option, secho as echo, pass_context from importlib import import_module
from click import argument, command, group, get_current_context, option, secho as echo, pass_context, CommandCollection
from collections import defaultdict, deque from collections import defaultdict, deque
from datetime import datetime from datetime import datetime
from fcntl import fcntl, F_SETFL, F_GETFL from fcntl import fcntl, F_SETFL, F_GETFL
@ -17,11 +18,12 @@ from hashlib import md5
from json import loads from json import loads
from multiprocessing import cpu_count from multiprocessing import cpu_count
from os import chmod, getgid, getuid, symlink, unlink, remove, stat, listdir, environ, makedirs, O_NONBLOCK from os import chmod, getgid, getuid, symlink, unlink, remove, stat, listdir, environ, makedirs, O_NONBLOCK
from os.path import abspath, basename, dirname, exists, getmtime, join, realpath, splitext from os.path import abspath, basename, dirname, exists, getmtime, join, realpath, splitext, isdir
from re import sub from re import sub
from shutil import copyfile, rmtree, which from shutil import copyfile, rmtree, which
from socket import socket, AF_INET, SOCK_STREAM from socket import socket, AF_INET, SOCK_STREAM
from sys import argv, stdin, stdout, stderr, version_info, exit from sys import argv, stdin, stdout, stderr, version_info, exit
from sys import path as sys_path
from stat import S_IRUSR, S_IWUSR, S_IXUSR from stat import S_IRUSR, S_IWUSR, S_IXUSR
from subprocess import call, check_output, Popen, STDOUT, PIPE from subprocess import call, check_output, Popen, STDOUT, PIPE
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
@ -41,6 +43,7 @@ if 'sbin' not in environ['PATH']:
PIKU_ROOT = environ.get('PIKU_ROOT', join(environ['HOME'],'.piku')) PIKU_ROOT = environ.get('PIKU_ROOT', join(environ['HOME'],'.piku'))
PIKU_BIN = join(environ['HOME'],'bin') PIKU_BIN = join(environ['HOME'],'bin')
PIKU_SCRIPT = realpath(__file__) PIKU_SCRIPT = realpath(__file__)
PLUGIN_ROOT = abspath(join(PIKU_ROOT, "plugins"))
APP_ROOT = abspath(join(PIKU_ROOT, "apps")) APP_ROOT = abspath(join(PIKU_ROOT, "apps"))
ENV_ROOT = abspath(join(PIKU_ROOT, "envs")) ENV_ROOT = abspath(join(PIKU_ROOT, "envs"))
GIT_ROOT = abspath(join(PIKU_ROOT, "repos")) GIT_ROOT = abspath(join(PIKU_ROOT, "repos"))
@ -1357,6 +1360,19 @@ def cmd_git_receive_pack(app):
# Handle the actual receive. We'll be called with 'git-hook' after it happens # Handle the actual receive. We'll be called with 'git-hook' after it happens
call('git-shell -c "{}" '.format(argv[1] + " '{}'".format(app)), cwd=GIT_ROOT, shell=True) call('git-shell -c "{}" '.format(argv[1] + " '{}'".format(app)), cwd=GIT_ROOT, shell=True)
def _get_plugin_commands(path):
sys_path.append(abspath(path))
cli_commands = []
for item in listdir(path):
module_path = join(path, item)
if not isdir(module_path):
continue
module = import_module(item)
if hasattr(module, 'cli_commands'):
cli_commands.append(module.cli_commands())
return cli_commands
@piku.command("help") @piku.command("help")
@pass_context @pass_context
@ -1366,4 +1382,7 @@ def cmd_help(ctx):
if __name__ == '__main__': if __name__ == '__main__':
piku() cli_commands = _get_plugin_commands(path=PLUGIN_ROOT)
cli_commands.append(piku)
cli = CommandCollection(sources=cli_commands)
cli()