forked from orbit-oss/flask
Merge pull request #1821 from pallets/feature/plugin-cli
Added plugin support to the cli
This commit is contained in:
commit
c73cf0f82e
2 changed files with 53 additions and 0 deletions
34
docs/cli.rst
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
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…
Add table
Add a link
Reference in a new issue