Mini Shell
"""The ``celery shell`` program, used to start a REPL."""
import os
import sys
from importlib import import_module
import click
from celery.bin.base import CeleryCommand, CeleryOption, handle_preload_options
def _invoke_fallback_shell(locals):
import code
try:
import readline
except ImportError:
pass
else:
import rlcompleter
readline.set_completer(
rlcompleter.Completer(locals).complete)
readline.parse_and_bind('tab:complete')
code.interact(local=locals)
def _invoke_bpython_shell(locals):
import bpython
bpython.embed(locals)
def _invoke_ipython_shell(locals):
for ip in (_ipython, _ipython_pre_10,
_ipython_terminal, _ipython_010,
_no_ipython):
try:
return ip(locals)
except ImportError:
pass
def _ipython(locals):
from IPython import start_ipython
start_ipython(argv=[], user_ns=locals)
def _ipython_pre_10(locals): # pragma: no cover
from IPython.frontend.terminal.ipapp import TerminalIPythonApp
app = TerminalIPythonApp.instance()
app.initialize(argv=[])
app.shell.user_ns.update(locals)
app.start()
def _ipython_terminal(locals): # pragma: no cover
from IPython.terminal import embed
embed.TerminalInteractiveShell(user_ns=locals).mainloop()
def _ipython_010(locals): # pragma: no cover
from IPython.Shell import IPShell
IPShell(argv=[], user_ns=locals).mainloop()
def _no_ipython(self): # pragma: no cover
raise ImportError('no suitable ipython found')
def _invoke_default_shell(locals):
try:
import IPython # noqa
except ImportError:
try:
import bpython # noqa
except ImportError:
_invoke_fallback_shell(locals)
else:
_invoke_bpython_shell(locals)
else:
_invoke_ipython_shell(locals)
@click.command(cls=CeleryCommand, context_settings={
'allow_extra_args': True
})
@click.option('-I',
'--ipython',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Force IPython.")
@click.option('-B',
'--bpython',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Force bpython.")
@click.option('--python',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Force default Python shell.")
@click.option('-T',
'--without-tasks',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Don't add tasks to locals.")
@click.option('--eventlet',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Use eventlet.")
@click.option('--gevent',
is_flag=True,
cls=CeleryOption,
help_group="Shell Options",
help="Use gevent.")
@click.pass_context
@handle_preload_options
def shell(ctx, ipython=False, bpython=False,
python=False, without_tasks=False, eventlet=False,
gevent=False, **kwargs):
"""Start shell session with convenient access to celery symbols.
The following symbols will be added to the main globals:
- ``celery``: the current application.
- ``chord``, ``group``, ``chain``, ``chunks``,
``xmap``, ``xstarmap`` ``subtask``, ``Task``
- all registered tasks.
"""
sys.path.insert(0, os.getcwd())
if eventlet:
import_module('celery.concurrency.eventlet')
if gevent:
import_module('celery.concurrency.gevent')
import celery
app = ctx.obj.app
app.loader.import_default_modules()
# pylint: disable=attribute-defined-outside-init
locals = {
'app': app,
'celery': app,
'Task': celery.Task,
'chord': celery.chord,
'group': celery.group,
'chain': celery.chain,
'chunks': celery.chunks,
'xmap': celery.xmap,
'xstarmap': celery.xstarmap,
'subtask': celery.subtask,
'signature': celery.signature,
}
if not without_tasks:
locals.update({
task.__name__: task for task in app.tasks.values()
if not task.name.startswith('celery.')
})
if python:
_invoke_fallback_shell(locals)
elif bpython:
try:
_invoke_bpython_shell(locals)
except ImportError:
ctx.obj.echo(f'{ctx.obj.ERROR}: bpython is not installed')
elif ipython:
try:
_invoke_ipython_shell(locals)
except ImportError as e:
ctx.obj.echo(f'{ctx.obj.ERROR}: {e}')
_invoke_default_shell(locals)
Zerion Mini Shell 1.0