Skip to content

Commit

Permalink
Docs, cleanup, and re-named plugin examples from Printer to PrintIt t…
Browse files Browse the repository at this point in the history
…o prevent accidentally installing a package on PyPI called printer.
  • Loading branch information
geowurster committed Jul 21, 2015
1 parent 3449769 commit 236503d
Show file tree
Hide file tree
Showing 27 changed files with 169 additions and 146 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ python:

install:
- pip install coveralls
- pip install -e .[test]
- pip install -e .[dev]

script:
- py.test tests --cov click_plugins --cov-report term-missing
Expand Down
5 changes: 5 additions & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Authors
=======

Kevin Wurster <[email protected]>
Sean Gillies <[email protected]>
5 changes: 3 additions & 2 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
Changelog
=========

1.0 - ?
-------

1.0 - 2015-07-20
----------------

Initial release.
5 changes: 3 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include AUTHORS.txt
include CHANGES.txt
include LICENSE.txt
include MANIFEST.in
include README.md
include setup.py
include README.rst
recursive-include tests *.py
72 changes: 41 additions & 31 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,33 @@ click-plugins
.. image:: https://coveralls.io/repos/click-contrib/click-plugins/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/click-contrib/click-plugins?branch=master

An extension module for `click <https://github.com/mitsuhiko/click>`_ to enable registering
An extension module for `click <https://github.com/mitsuhiko/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 be very difficult to integrate
into the current codebase, 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 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 where it IS registered. You
could have all plugins register alongside the core commands, in a special sub-group,
across multiple sub-groups, or some combination.
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 <js/examples>`_ section.
For a more detailed example see the `examples <https://github.com/click-contrib/click-plugins/tree/master/examples>`_ section.

The only requirement is decorating ``click.group()`` with another decorator
that attaches the external ``click.command()`` or ``click.group()``.
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
Expand All @@ -43,7 +44,7 @@ that attaches the external ``click.command()`` or ``click.group()``.
from click_plugins import with_plugins
@with_plugins(iter_entry_points('yourpackage.cli_plugins'))
@with_plugins(iter_entry_points('core_package.cli_plugins'))
@click.group()
def cli():
"""Commandline interface for yourpackage."""
Expand All @@ -57,10 +58,7 @@ Developing Plugins
------------------

Plugin developers need to register their sub-commands or sub-groups to an
entry-point

same entry point
in their ``setup.py``.
entry-point in their ``setup.py`` that is loaded by the core package.

.. code-block:: python
Expand All @@ -71,10 +69,10 @@ in their ``setup.py``.
version='0.1',
py_modules=['yourscript'],
install_requires=[
'Click',
'click',
],
entry_points='''
[console_scripts]
[core_package.cli_plugins]
cool_subcommand=yourscript.cli:cool_subcommand
another_subcommand=yourscript.cli:another_subcommand
''',
Expand All @@ -98,17 +96,17 @@ and if the sub-command or group is executed the entire traceback is printed.
Best Practices and Extra Credit
-------------------------------

Opening a CLI to external plugins encourages other developers to independently
extend functionality on their own but their is no guarantee that their own
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 ``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.
Opening a CLI to plugins encourages other developers to independently extend
functionality independently but their 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
Expand Down Expand Up @@ -167,11 +165,23 @@ Developing
$ git clone https://github.com/click-contrib/click-plugins.git
$ cd click-plugins
$ virtualenv venv && source venv/bin/activate
$ pip install -e .[test]
$ pip install -e .[dev]
$ py.test tests --cov click_plugins --cov-report term-missing
Changelog
---------

See ``CHANGES.txt``


Authors
-------

See ``AUTHORS.txt``


License
-------

See ``LICENSE.txt``.
See ``LICENSE.txt``
4 changes: 2 additions & 2 deletions click_plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def subcommand(arg):

__version__ = '1.0'
__author__ = 'Kevin Wurster, Sean Gillies'
__email__ = '[email protected]'
__source__ = 'https://github.com/geowurster/click_plugins'
__email__ = '[email protected], [email protected]'
__source__ = 'https://github.com/click-contrib/click-plugins'
__license__ = '''
New BSD License
Expand Down
5 changes: 5 additions & 0 deletions example/PrintIt/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PrintIt
=======

This represents a core package with a CLI that registers external plugins. All
it does is print stuff.
File renamed without changes.
6 changes: 3 additions & 3 deletions example/printer/cli.py → example/PrintIt/printit/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Commandline interface for printer
Commandline interface for PrintIt
"""


Expand All @@ -9,7 +9,7 @@
from click_plugins import with_plugins


@with_plugins(iter_entry_points('printer.plugins'))
@with_plugins(iter_entry_points('printit.plugins'))
@click.group()
def cli():

Expand All @@ -19,7 +19,7 @@ def cli():
\b
For example:
\b
$ cat README.rst | printer lower
$ cat README.rst | printit lower
"""


Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions example/setup.py → example/PrintIt/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@


"""
Setup script for `printer`
Setup script for `PrintIt`
"""


from setuptools import setup


setup(
name='printer',
name='PrintIt',
version='0.1dev0',
packages=['printer'],
packages=['printit'],
entry_points='''
[console_scripts]
printer=printer.cli:cli
printit=printit.cli:cli
'''
)
5 changes: 5 additions & 0 deletions example/PrintItBold/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PrintItBold
===========

This plugin should add bold styling to ``PrintIt`` but there is a typo in the
entry point section of the ``setup.py`` that prevents the plugin from loading.
3 changes: 3 additions & 0 deletions example/PrintItBold/printit_bold/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
A CLI plugin for `PrintIt` that adds bold text.
"""
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Add bold styling to `printer`
Add bold styling to `printit`
"""


Expand Down
20 changes: 20 additions & 0 deletions example/PrintItBold/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env python


"""
Setup script for `PrintItBold`
"""


from setuptools import setup


setup(
name='PrintItBold',
version='0.1dev0',
packages=['printit_bold'],
entry_points='''
[printit.plugins]
bold=printit_bold.core:bolddddddddddd
'''
)
4 changes: 4 additions & 0 deletions example/PrintItStyle/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PrintItStyle
============

A plugin for ``PrintIt`` that adds commands for text styling.
3 changes: 3 additions & 0 deletions example/PrintItStyle/printit_style/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
A CLI plugin for `PrintIt` that adds styling options.
"""
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Core components for printer_style
Core components for `PrintItStyle`
"""


Expand Down
21 changes: 21 additions & 0 deletions example/PrintItStyle/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python


"""
Setup script for `PrintItStyle`
"""


from setuptools import setup


setup(
name='PrintItStyle',
version='0.1dev0',
packages=['printit_style'],
entry_points='''
[printit.plugins]
background=printit_style.core:background
color=printit_style.core:color
'''
)
5 changes: 0 additions & 5 deletions example/PrinterBold/README.rst

This file was deleted.

3 changes: 0 additions & 3 deletions example/PrinterBold/printer_bold/__init__.py

This file was deleted.

20 changes: 0 additions & 20 deletions example/PrinterBold/setup.py

This file was deleted.

12 changes: 0 additions & 12 deletions example/PrinterStyle/README.rst

This file was deleted.

3 changes: 0 additions & 3 deletions example/PrinterStyle/printer_style/__init__.py

This file was deleted.

21 changes: 0 additions & 21 deletions example/PrinterStyle/setup.py

This file was deleted.

Loading

0 comments on commit 236503d

Please sign in to comment.