104 lines
3.4 KiB
Python
104 lines
3.4 KiB
Python
from functools import wraps
|
|
from collections import OrderedDict
|
|
|
|
|
|
def _embed_ipython_shell(namespace={}, banner=''):
|
|
"""Start an IPython Shell"""
|
|
try:
|
|
from IPython.terminal.embed import InteractiveShellEmbed
|
|
from IPython.terminal.ipapp import load_default_config
|
|
except ImportError:
|
|
from IPython.frontend.terminal.embed import InteractiveShellEmbed
|
|
from IPython.frontend.terminal.ipapp import load_default_config
|
|
|
|
@wraps(_embed_ipython_shell)
|
|
def wrapper(namespace=namespace, banner=''):
|
|
config = load_default_config()
|
|
# Always use .instace() to ensure _instance propagation to all parents
|
|
# this is needed for <TAB> completion works well for new imports
|
|
# and clear the instance to always have the fresh env
|
|
# on repeated breaks like with inspect_response()
|
|
InteractiveShellEmbed.clear_instance()
|
|
shell = InteractiveShellEmbed.instance(
|
|
banner1=banner, user_ns=namespace, config=config)
|
|
shell()
|
|
return wrapper
|
|
|
|
|
|
def _embed_bpython_shell(namespace={}, banner=''):
|
|
"""Start a bpython shell"""
|
|
import bpython
|
|
|
|
@wraps(_embed_bpython_shell)
|
|
def wrapper(namespace=namespace, banner=''):
|
|
bpython.embed(locals_=namespace, banner=banner)
|
|
return wrapper
|
|
|
|
|
|
def _embed_ptpython_shell(namespace={}, banner=''):
|
|
"""Start a ptpython shell"""
|
|
import ptpython.repl
|
|
|
|
@wraps(_embed_ptpython_shell)
|
|
def wrapper(namespace=namespace, banner=''):
|
|
print(banner)
|
|
ptpython.repl.embed(locals=namespace)
|
|
return wrapper
|
|
|
|
|
|
def _embed_standard_shell(namespace={}, banner=''):
|
|
"""Start a standard python shell"""
|
|
import code
|
|
try: # readline module is only available on unix systems
|
|
import readline
|
|
except ImportError:
|
|
pass
|
|
else:
|
|
import rlcompleter # noqa: F401
|
|
readline.parse_and_bind("tab:complete")
|
|
|
|
@wraps(_embed_standard_shell)
|
|
def wrapper(namespace=namespace, banner=''):
|
|
code.interact(banner=banner, local=namespace)
|
|
return wrapper
|
|
|
|
|
|
DEFAULT_PYTHON_SHELLS = OrderedDict([
|
|
('ptpython', _embed_ptpython_shell),
|
|
('ipython', _embed_ipython_shell),
|
|
('bpython', _embed_bpython_shell),
|
|
('python', _embed_standard_shell),
|
|
])
|
|
|
|
|
|
def get_shell_embed_func(shells=None, known_shells=None):
|
|
"""Return the first acceptable shell-embed function
|
|
from a given list of shell names.
|
|
"""
|
|
if shells is None: # list, preference order of shells
|
|
shells = DEFAULT_PYTHON_SHELLS.keys()
|
|
if known_shells is None: # available embeddable shells
|
|
known_shells = DEFAULT_PYTHON_SHELLS.copy()
|
|
for shell in shells:
|
|
if shell in known_shells:
|
|
try:
|
|
# function test: run all setup code (imports),
|
|
# but dont fall into the shell
|
|
return known_shells[shell]()
|
|
except ImportError:
|
|
continue
|
|
|
|
|
|
def start_python_console(namespace=None, banner='', shells=None):
|
|
"""Start Python console bound to the given namespace.
|
|
Readline support and tab completion will be used on Unix, if available.
|
|
"""
|
|
if namespace is None:
|
|
namespace = {}
|
|
|
|
try:
|
|
shell = get_shell_embed_func(shells)
|
|
if shell is not None:
|
|
shell(namespace=namespace, banner=banner)
|
|
except SystemExit: # raised when using exit() in python code.interact
|
|
pass
|