single |
=============
click-plugins
=============
An extension module for [click] to register
external CLI commands via setuptools entry-points.
Why?
----
Lets say you develop a commandline interface and someone requests a new
feature
that is absolutely related to your project but would have negative
consequences
like additional dependencies, major refactoring, or maybe its just too
domain
specific to be supported directly. Rather than developing a separate
standalone
utility you could offer up a [setuptools entry point]
that allows others to use your commandline utility as a home for their
related
sub-commands. You get to choose where these sub-commands or sub-groups CAN
be
registered but the plugin developer gets to choose they ARE registered.
You
could have all plugins register alongside the core commands, in a special
sub-group, across multiple sub-groups, or some combination.
Enabling Plugins
----------------
For a more detailed example see the [examples] section.
The only requirement is decorating ``click.group() with
click_plugins.with_plugins()``
which handles attaching external commands and groups. In this case the
core CLI developer
registers CLI plugins from ``core_package.cli_plugins``.
.. code-block:: python
from pkg_resources import iter_entry_points
import click
from click_plugins import with_plugins
@with_plugins(iter_entry_points('core_package.cli_plugins'))
@click.group()
def cli():
"""Commandline interface for yourpackage."""
@cli.command()
def subcommand():
"""Subcommand that does something."""
Developing Plugins
------------------
Plugin developers need to register their sub-commands or sub-groups to an
entry-point in their ``setup.py`` that is loaded by the core package.
.. code-block:: python
from setuptools import setup
setup(
name='yourscript',
version='0.1',
py_modules=['yourscript'],
install_requires=[
'click',
],
entry_points='''
[core_package.cli_plugins]
cool_subcommand=yourscript.cli:cool_subcommand
another_subcommand=yourscript.cli:another_subcommand
''',
)
Broken and Incompatible Plugins
-------------------------------
Any sub-command or sub-group that cannot be loaded is caught and converted
to
a ``click_plugins.core.BrokenCommand()`` rather than just crashing the
entire
CLI. The short-help is converted to a warning message like:
.. code-block:: console
Warning: could not load plugin. See `` --help``.
and if the sub-command or group is executed the entire traceback is
printed.
Best Practices and Extra Credit
-------------------------------
Opening a CLI to plugins encourages other developers to independently
extend
|