AppGroup
is a class within the flask.cli
module of the Flask project. It
works like the
Click Group
class and automatically wraps the functions using
with_appcontext.
DispatchingApp,
FlaskGroup,
ScriptInfo,
pass_script_info,
and with_appcontext
are several other callables with code examples from the same flask.cli
package.
indico (project website, documentation and sandbox demo) is a Flask-based web app for event management. The code is open sourced under the MIT license.
indico / indico / cli / util.py
# util.py
import traceback
from importlib import import_module
import click
from flask.cli import AppGroup, FlaskGroup, ScriptInfo
from flask_pluginengine import wrap_in_plugin_context
from werkzeug.utils import cached_property
def _create_app(info):
from indico.web.flask.app import make_app
return make_app()
class IndicoFlaskGroup(FlaskGroup):
def __init__(self, **extra):
super().__init__(create_app=_create_app, add_default_commands=False, add_version_option=False,
set_debug_flag=False, **extra)
self._indico_plugin_commands = None
def _load_plugin_commands(self):
assert False
def _wrap_in_plugin_context(self, plugin, cmd):
cmd.callback = wrap_in_plugin_context(plugin, cmd.callback)
for subcmd in getattr(cmd, 'commands', {}).values():
self._wrap_in_plugin_context(plugin, subcmd)
def _get_indico_plugin_commands(self, ctx):
if self._indico_plugin_commands is not None:
return self._indico_plugin_commands
try:
from indico.core import signals
from indico.util.signals import named_objects_from_signal
ctx.ensure_object(ScriptInfo).load_app()
cmds = named_objects_from_signal(signals.plugin.cli.send(), plugin_attr='_indico_plugin')
rv = {}
for name, cmd in cmds.items():
if cmd._indico_plugin:
self._wrap_in_plugin_context(cmd._indico_plugin, cmd)
rv[name] = cmd
except Exception as exc:
if 'No indico config found' not in str(exc):
click.echo(click.style('Loading plugin commands failed:', fg='red', bold=True))
click.echo(click.style(traceback.format_exc(), fg='red'))
rv = {}
self._indico_plugin_commands = rv
return rv
def get_command(self, ctx, name):
rv = AppGroup.get_command(self, ctx, name)
if rv is not None:
return rv
return self._get_indico_plugin_commands(ctx).get(name)
def list_commands(self, ctx):
rv = set(click.Group.list_commands(self, ctx))
rv.update(self._get_indico_plugin_commands(ctx))
return sorted(rv)
class LazyGroup(click.Group):
def __init__(self, import_name, **kwargs):
self._import_name = import_name
super().__init__(**kwargs)
@cached_property
def _impl(self):
module, name = self._import_name.split(':', 1)
return getattr(import_module(module), name)
def get_command(self, ctx, cmd_name):
return self._impl.get_command(ctx, cmd_name)
## ... source file continues with no further AppGroup examples...