Browse Source

Merge pull request #1821 from pallets/feature/plugin-cli

Added plugin support to the cli
pull/1823/head
Armin Ronacher 9 years ago
parent
commit
c73cf0f82e
  1. 34
      docs/cli.rst
  2. 19
      flask/cli.py

34
docs/cli.rst

@ -214,3 +214,37 @@ step.
Whenever click now needs to operate on a Flask application it will Whenever click now needs to operate on a Flask application it will
call that function with the script info and ask for it to be created. call that function with the script info and ask for it to be created.
4. All is rounded up by invoking the script. 4. All is rounded up by invoking the script.
CLI Plugins
-----------
Flask extensions can always patch the `Flask.cli` instance with more
commands if they want. However there is a second way to add CLI plugins
to Flask which is through `setuptools`. If you make a Python package that
should export a Flask command line plugin you can ship a `setup.py` file
that declares an entrypoint that points to a click command:
Example `setup.py`::
from setuptools import setup
setup(
name='flask-my-extension',
...
entry_points='''
[flask.commands]
my-command=mypackage.commands:cli
''',
)
Inside `mypackage/comamnds.py` you can then export a Click object::
import click
@click.command()
def cli():
"""This is an example command."""
Once that package is installed in the same virtualenv as Flask itself you
can run ``flask my-command`` to invoke your command. This is useful to
provide extra functionality that Flask itself cannot ship.

19
flask/cli.py

@ -282,7 +282,24 @@ class FlaskGroup(AppGroup):
self.add_command(run_command) self.add_command(run_command)
self.add_command(shell_command) self.add_command(shell_command)
self._loaded_plugin_commands = False
def _load_plugin_commands(self):
if self._loaded_plugin_commands:
return
try:
import pkg_resources
except ImportError:
self._loaded_plugin_commands = True
return
for ep in pkg_resources.iter_entry_points('flask.commands'):
self.add_command(ep.load(), ep.name)
self._loaded_plugin_commands = True
def get_command(self, ctx, name): def get_command(self, ctx, name):
self._load_plugin_commands()
# We load built-in commands first as these should always be the # We load built-in commands first as these should always be the
# same no matter what the app does. If the app does want to # same no matter what the app does. If the app does want to
# override this it needs to make a custom instance of this group # override this it needs to make a custom instance of this group
@ -303,6 +320,8 @@ class FlaskGroup(AppGroup):
pass pass
def list_commands(self, ctx): def list_commands(self, ctx):
self._load_plugin_commands()
# The commands available is the list of both the application (if # The commands available is the list of both the application (if
# available) plus the builtin commands. # available) plus the builtin commands.
rv = set(click.Group.list_commands(self, ctx)) rv = set(click.Group.list_commands(self, ctx))

Loading…
Cancel
Save