1"""Simple function for embedding an IPython kernel
2"""
3#-----------------------------------------------------------------------------
4# Imports
5#-----------------------------------------------------------------------------
6
7import sys
8
9from IPython.utils.frame import extract_module_locals
10
11from .kernelapp import IPKernelApp
12
13#-----------------------------------------------------------------------------
14# Code
15#-----------------------------------------------------------------------------
16
17def embed_kernel(module=None, local_ns=None, **kwargs):
18    """Embed and start an IPython kernel in a given scope.
19
20    Parameters
21    ----------
22    module : ModuleType, optional
23        The module to load into IPython globals (default: caller)
24    local_ns : dict, optional
25        The namespace to load into IPython user namespace (default: caller)
26    **kwargs : various, optional
27        Further keyword args are relayed to the IPKernelApp constructor,
28        allowing configuration of the Kernel.  Will only have an effect
29        on the first embed_kernel call for a given process.
30
31    """
32    # get the app if it exists, or set it up if it doesn't
33    if IPKernelApp.initialized():
34        app = IPKernelApp.instance()
35    else:
36        app = IPKernelApp.instance(**kwargs)
37        app.initialize([])
38        # Undo unnecessary sys module mangling from init_sys_modules.
39        # This would not be necessary if we could prevent it
40        # in the first place by using a different InteractiveShell
41        # subclass, as in the regular embed case.
42        main = app.kernel.shell._orig_sys_modules_main_mod
43        if main is not None:
44            sys.modules[app.kernel.shell._orig_sys_modules_main_name] = main
45
46    # load the calling scope if not given
47    (caller_module, caller_locals) = extract_module_locals(1)
48    if module is None:
49        module = caller_module
50    if local_ns is None:
51        local_ns = caller_locals
52
53    app.kernel.user_module = module
54    app.kernel.user_ns = local_ns
55    app.shell.set_completer_frame()
56    app.start()
57