Add Blueprint level cli command registration

Implements #1357.
Adds ability to register click cli commands onto blueprint.
This commit is contained in:
Anthony Plunkett 2018-05-14 22:05:54 -04:00 committed by David Lord
parent 855d59b68b
commit ec1ccd7530
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
6 changed files with 136 additions and 8 deletions

View file

@ -600,13 +600,9 @@ class Flask(_PackageBoundObject):
view_func=self.send_static_file,
)
#: The click command line context for this application. Commands
#: registered here show up in the :command:`flask` command once the
#: application has been discovered. The default commands are
#: provided by Flask itself and can be overridden.
#:
#: This is an instance of a :class:`click.Group` object.
self.cli = cli.AppGroup(self.name)
# Set the name of the Click group in case someone wants to add
# the app's commands to another CLI tool.
self.cli.name = self.name
@locked_cached_property
def name(self):

View file

@ -13,6 +13,9 @@ from functools import update_wrapper
from .helpers import _PackageBoundObject, _endpoint_from_view_func
# a singleton sentinel value for parameter defaults
_sentinel = object()
class BlueprintSetupState(object):
"""Temporary holder object for registering a blueprint with the
@ -90,6 +93,11 @@ class Blueprint(_PackageBoundObject):
or other things on the main application. See :ref:`blueprints` for more
information.
.. versionchanged:: 1.1.0
Blueprints have a ``cli`` group to register nested CLI commands.
The ``cli_group`` parameter controls the name of the group under
the ``flask`` command.
.. versionadded:: 0.7
"""
@ -129,6 +137,7 @@ class Blueprint(_PackageBoundObject):
subdomain=None,
url_defaults=None,
root_path=None,
cli_group=_sentinel,
):
_PackageBoundObject.__init__(
self, import_name, template_folder, root_path=root_path
@ -142,6 +151,7 @@ class Blueprint(_PackageBoundObject):
if url_defaults is None:
url_defaults = {}
self.url_values_defaults = url_defaults
self.cli_group = cli_group
def record(self, func):
"""Registers a function that is called when the blueprint is
@ -206,6 +216,17 @@ class Blueprint(_PackageBoundObject):
for deferred in self.deferred_functions:
deferred(state)
cli_resolved_group = options.get("cli_group", self.cli_group)
if cli_resolved_group is None:
app.cli.commands.update(self.cli.commands)
elif cli_resolved_group is _sentinel:
self.cli.name = self.name
app.cli.add_command(self.cli)
else:
self.cli.name = cli_resolved_group
app.cli.add_command(self.cli)
def route(self, rule, **options):
"""Like :meth:`Flask.route` but for a blueprint. The endpoint for the
:func:`url_for` function is prefixed with the name of the blueprint.

View file

@ -942,6 +942,15 @@ class _PackageBoundObject(object):
self._static_folder = None
self._static_url_path = None
# circular import
from .cli import AppGroup
#: The Click command group for registration of CLI commands
#: on the application and associated blueprints. These commands
#: are accessible via the :command:`flask` command once the
#: application has been discovered and blueprints registered.
self.cli = AppGroup()
def _get_static_folder(self):
if self._static_folder is not None:
return os.path.join(self.root_path, self._static_folder)