6
0
mirror of https://github.com/ChristianLight/tutor.git synced 2024-12-12 06:07:56 +00:00

Make it possible to run plugin subcommands

This commit is contained in:
Régis Behmo 2019-12-12 17:23:46 +01:00
parent 13de3c8adc
commit 0b1cac5134
5 changed files with 48 additions and 10 deletions

View File

@ -4,7 +4,8 @@ Note: Breaking changes between versions are indicated by "💥".
## Unreleased
- [Improvement] Move ``-r/--root`` option to parent command level
- [Feature] Add plugin subcommands
- 💥[Improvement] Move ``-r/--root`` option to parent command level
- [Bugfix] Fix course about page visibility
- [Improvement] Print gunicorn access logs in the console
- 💥[Improvement] Get rid of the `indexcourses` and `portainer` command (#269)

View File

@ -175,6 +175,43 @@ Example::
With the above declaration, you can store plugin-specific templates in the ``templates/myplugin`` folder next to the ``plugin.py`` file.
``command``
~~~~~~~~~~~
A plugin can provide custom command line commands. Commands are assumed to be `click.Command <https://click.palletsprojects.com/en/7.x/api/#commands>`__ objects.
Example::
import click
@click.command(help="I'm a plugin command")
def command():
click.echo("Hello from myplugin!")
Any user who installs the ``myplugin`` plugin can then run::
$ tutor myplugin
Hello from myplugin!
You can even define subcommands by creating `command groups <https://click.palletsprojects.com/en/7.x/api/#click.Group>`__::
import click
@click.group(help="I'm a plugin command group")
def command():
pass
@click.command(help="I'm a plugin subcommand")
def dosomething():
click.echo("This subcommand is awesome")
This would allow any user to run::
$ tutor myplugin dosomething
This subcommand is awesome
See the official `click documentation <https://click.palletsprojects.com/en/7.x/>`__ for more information.
Creating a new plugin
---------------------

View File

@ -11,7 +11,7 @@ from .dev import dev
from .images import images_command
from .k8s import k8s
from .local import local
from .plugins import plugins_command
from .plugins import plugins_command, add_plugin_commands
from .ui import ui
from .webui import webui
from ..__about__ import __version__
@ -66,6 +66,7 @@ cli.add_command(ui)
cli.add_command(webui)
cli.add_command(print_help)
cli.add_command(plugins_command)
add_plugin_commands(cli)
if __name__ == "__main__":
main()

View File

@ -62,14 +62,15 @@ def disable(context, plugin_names):
)
def iter_extra_plugin_commands():
def add_plugin_commands(command_group):
"""
TODO document this. Merge with plugins.iter_commands? It's good to keepo
click-related stuff outside of the plugins module.
Add commands provided by all plugins to the given command group. Each command is
added with a name that is equal to the plugin name.
"""
for plugin_name, command in plugins.iter_commands():
if isinstance(command, click.Command):
command.name = plugin_name
yield command
command_group.add_command(command)
plugins_command.add_command(list_command)

View File

@ -160,9 +160,7 @@ def iter_templates(config):
def iter_commands():
"""
TODO doesn't this slow down the cli? (we need to import all plugins)
Also, do we really need the `config` argument? Do we want to make it possible for disabled plugins to be loaded?
TODO document this
Iterate over all plugins that provide a `command` attribute.
"""
for plugin_name, plugin in iter_installed():
command = getattr(plugin, "command", None)