Updates
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
Metadata-Version: 2.4
|
||||
Name: click-plugins
|
||||
Version: 1.1.1.2
|
||||
Summary: An extension module for click to enable registering CLI commands via setuptools entry-points.
|
||||
Home-page: https://github.com/click-contrib/click-plugins
|
||||
Author: Kevin Wurster, Sean Gillies
|
||||
Author-email: wursterk@gmail.com, sean.gillies@gmail.com
|
||||
License: New BSD
|
||||
Keywords: click plugin setuptools entry-point
|
||||
Classifier: Topic :: Utilities
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Development Status :: 7 - Inactive
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
License-File: LICENSE.txt
|
||||
License-File: AUTHORS.txt
|
||||
Requires-Dist: click>=4.0
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pytest>=3.6; extra == "dev"
|
||||
Requires-Dist: pytest-cov; extra == "dev"
|
||||
Requires-Dist: wheel; extra == "dev"
|
||||
Requires-Dist: coveralls; extra == "dev"
|
||||
Dynamic: author
|
||||
Dynamic: author-email
|
||||
Dynamic: classifier
|
||||
Dynamic: description
|
||||
Dynamic: home-page
|
||||
Dynamic: keywords
|
||||
Dynamic: license
|
||||
Dynamic: license-file
|
||||
Dynamic: provides-extra
|
||||
Dynamic: requires-dist
|
||||
Dynamic: summary
|
||||
|
||||
=============
|
||||
click-plugins
|
||||
=============
|
||||
|
||||
This PyPI package is no longer actively maintained, but the underlying
|
||||
library can be vendored. See `homepage <https://github.com/click-contrib/click-plugins>`_
|
||||
for more information.
|
||||
|
||||
An extension module for `click <https://github.com/pallets/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 <https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins>`_
|
||||
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 <https://github.com/click-contrib/click-plugins/tree/master/example>`_ 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 ``<CLI> <command/group> --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
|
||||
functionality independently but there is no guarantee these new features will
|
||||
be "on brand". Plugin developers are almost certainly already using features
|
||||
in the core package the CLI belongs to so defining commonly used arguments and
|
||||
options in one place lets plugin developers reuse these flags to produce a more
|
||||
cohesive CLI. If the CLI is simple maybe just define them at the top of
|
||||
``yourpackage/cli.py`` or for more complex packages something like
|
||||
``yourpackage/cli/options.py``. These common options need to be easy to find
|
||||
and be well documented so that plugin developers know what variable to give to
|
||||
their sub-command's function and what object they can expect to receive. Don't
|
||||
forget to document non-obvious callbacks.
|
||||
|
||||
Keep in mind that plugin developers also have access to the parent group's
|
||||
``ctx.obj``, which is very useful for passing things like verbosity levels or
|
||||
config values around to sub-commands.
|
||||
|
||||
Here's some code that sub-commands could re-use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from multiprocessing import cpu_count
|
||||
|
||||
import click
|
||||
|
||||
jobs_opt = click.option(
|
||||
'-j', '--jobs', metavar='CORES', type=click.IntRange(min=1, max=cpu_count()), default=1,
|
||||
show_default=True, help="Process data across N cores."
|
||||
)
|
||||
|
||||
Plugin developers can access this with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import click
|
||||
import parent_cli_package.cli.options
|
||||
|
||||
|
||||
@click.command()
|
||||
@parent_cli_package.cli.options.jobs_opt
|
||||
def subcommand(jobs):
|
||||
"""I do something domain specific."""
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
With ``pip``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install click-plugins
|
||||
|
||||
From source:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ git clone https://github.com/click-contrib/click-plugins.git
|
||||
$ cd click-plugins
|
||||
$ python setup.py install
|
||||
|
||||
|
||||
Developing
|
||||
----------
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ git clone https://github.com/click-contrib/click-plugins.git
|
||||
$ cd click-plugins
|
||||
$ pip install -e .\[dev\]
|
||||
$ pytest tests --cov click_plugins --cov-report term-missing
|
||||
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
See ``CHANGES.txt``
|
||||
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
See ``AUTHORS.txt``
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
See ``LICENSE.txt``
|
||||
Reference in New Issue
Block a user