shell.py
274 lines
| 10.3 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2157 | #!/usr/bin/env python | ||
# encoding: utf-8 | ||||
Ville M. Vainio
|
r1032 | """IPython Shell classes. | ||
Brian Granger
|
r2070 | Originally, this module was horribly complicated because of the need to | ||
use threads to integrate with GUI toolkit event loops. Now, we are using | ||||
the :mod:`IPython.lib.inputhook`, which is based on PyOS_InputHook. This | ||||
dramatically simplifies this logic and allow 3rd party packages (such as | ||||
matplotlib) to handle these things by themselves. | ||||
This new approach also allows projects like matplotlib to work interactively | ||||
in the standard python shell. | ||||
Fernando Perez
|
r1853 | """ | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | #----------------------------------------------------------------------------- | ||
# Copyright (C) 2008-2009 The IPython Development Team | ||||
Ville M. Vainio
|
r1032 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
Brian Granger
|
r2070 | #----------------------------------------------------------------------------- | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | #----------------------------------------------------------------------------- | ||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | import sys | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2048 | from IPython.core import ultratb | ||
Brian Granger
|
r2027 | from IPython.core import ipapi | ||
Brian Granger
|
r2070 | from IPython.utils.genutils import ask_yes_no | ||
Brian Granger
|
r2028 | from IPython.core.iplib import InteractiveShell | ||
Brian Granger
|
r2029 | from IPython.core.ipmaker import make_IPython | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | #----------------------------------------------------------------------------- | ||
# Code | ||||
#----------------------------------------------------------------------------- | ||||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | class IPShell: | ||
"""Create an IPython instance. | ||||
Fernando Perez
|
r1401 | |||
Brian Granger
|
r2070 | This calls the factory :func:`make_IPython`, which creates a configured | ||
:class:`InteractiveShell` object, and presents the result as a simple | ||||
class with a :meth:`mainloop` method. | ||||
""" | ||||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | def __init__(self, argv=None, user_ns=None, user_global_ns=None, | ||
debug=1, shell_class=InteractiveShell): | ||||
self.IP = make_IPython(argv, user_ns=user_ns, | ||||
Ville M. Vainio
|
r1032 | user_global_ns=user_global_ns, | ||
Brian Granger
|
r2070 | debug=debug, shell_class=shell_class) | ||
Ville M. Vainio
|
r1032 | |||
def mainloop(self,sys_exit=0,banner=None): | ||||
self.IP.mainloop(banner) | ||||
if sys_exit: | ||||
sys.exit() | ||||
Brian Granger
|
r2070 | |||
# This is an additional magic that is exposed in embedded shells. | ||||
Ville M. Vainio
|
r1032 | def kill_embedded(self,parameter_s=''): | ||
"""%kill_embedded : deactivate for good the current embedded IPython. | ||||
This function (after asking for confirmation) sets an internal flag so that | ||||
an embedded IPython will never activate again. This is useful to | ||||
permanently disable a shell that is being called inside a loop: once you've | ||||
figured out what you needed from it, you may then kill it and the program | ||||
will then continue to run without the interactive shell interfering again. | ||||
""" | ||||
kill = ask_yes_no("Are you sure you want to kill this embedded instance " | ||||
"(y/n)? [y/N] ",'n') | ||||
if kill: | ||||
self.shell.embedded_active = False | ||||
print "This embedded IPython will not reactivate anymore once you exit." | ||||
Brian Granger
|
r2070 | |||
Ville M. Vainio
|
r1032 | class IPShellEmbed: | ||
"""Allow embedding an IPython shell into a running program. | ||||
Instances of this class are callable, with the __call__ method being an | ||||
alias to the embed() method of an InteractiveShell instance. | ||||
Brian Granger
|
r2070 | Usage (see also the example-embed.py file for a running example):: | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override]) | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | * argv: list containing valid command-line options for IPython, as they | ||
Ville M. Vainio
|
r1032 | would appear in sys.argv[1:]. | ||
Brian Granger
|
r2070 | For example, the following command-line options:: | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | $ ipython -prompt_in1 'Input <\\#>' -colors LightBG | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | would be passed in the argv list as:: | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | ['-prompt_in1','Input <\\#>','-colors','LightBG'] | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | * banner: string which gets printed every time the interpreter starts. | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | * exit_msg: string which gets printed every time the interpreter exits. | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | * rc_override: a dict or Struct of configuration options such as those | ||
Ville M. Vainio
|
r1032 | used by IPython. These options are read from your ~/.ipython/ipythonrc | ||
file when the Shell object is created. Passing an explicit rc_override | ||||
dict with any options you want allows you to override those values at | ||||
creation time without having to modify the file. This way you can create | ||||
embeddable instances configured in any way you want without editing any | ||||
global files (thus keeping your interactive IPython configuration | ||||
unchanged). | ||||
Brian Granger
|
r2070 | Then the ipshell instance can be called anywhere inside your code:: | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | ipshell(header='') -> Opens up an IPython shell. | ||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | * header: string printed by the IPython shell upon startup. This can let | ||
Ville M. Vainio
|
r1032 | you know where in your code you are when dropping into the shell. Note | ||
that 'banner' gets prepended to all calls, so header is used for | ||||
location-specific information. | ||||
For more details, see the __call__ method below. | ||||
When the IPython shell is exited with Ctrl-D, normal program execution | ||||
resumes. | ||||
This functionality was inspired by a posting on comp.lang.python by cmkl | ||||
<cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and | ||||
Brian Granger
|
r2070 | by the IDL stop/continue commands. | ||
""" | ||||
Ville M. Vainio
|
r1032 | |||
Brian Granger
|
r2070 | def __init__(self, argv=None, banner='', exit_msg=None, | ||
rc_override=None, user_ns=None): | ||||
Ville M. Vainio
|
r1032 | """Note that argv here is a string, NOT a list.""" | ||
Brian Granger
|
r2070 | |||
Ville M. Vainio
|
r1032 | self.set_banner(banner) | ||
self.set_exit_msg(exit_msg) | ||||
self.set_dummy_mode(0) | ||||
# sys.displayhook is a global, we need to save the user's original | ||||
# Don't rely on __displayhook__, as the user may have changed that. | ||||
self.sys_displayhook_ori = sys.displayhook | ||||
# save readline completer status | ||||
try: | ||||
#print 'Save completer',sys.ipcompleter # dbg | ||||
self.sys_ipcompleter_ori = sys.ipcompleter | ||||
except: | ||||
pass # not nested with IPython | ||||
self.IP = make_IPython(argv,rc_override=rc_override, | ||||
embedded=True, | ||||
user_ns=user_ns) | ||||
ip = ipapi.IPApi(self.IP) | ||||
ip.expose_magic("kill_embedded",kill_embedded) | ||||
# copy our own displayhook also | ||||
self.sys_displayhook_embed = sys.displayhook | ||||
# and leave the system's display hook clean | ||||
sys.displayhook = self.sys_displayhook_ori | ||||
# don't use the ipython crash handler so that user exceptions aren't | ||||
# trapped | ||||
Brian Granger
|
r2048 | sys.excepthook = ultratb.FormattedTB(color_scheme = self.IP.rc.colors, | ||
Ville M. Vainio
|
r1032 | mode = self.IP.rc.xmode, | ||
call_pdb = self.IP.rc.pdb) | ||||
self.restore_system_completer() | ||||
def restore_system_completer(self): | ||||
"""Restores the readline completer which was in place. | ||||
This allows embedded IPython within IPython not to disrupt the | ||||
parent's completion. | ||||
""" | ||||
try: | ||||
self.IP.readline.set_completer(self.sys_ipcompleter_ori) | ||||
sys.ipcompleter = self.sys_ipcompleter_ori | ||||
except: | ||||
pass | ||||
Brian Granger
|
r2070 | def __call__(self, header='', local_ns=None, global_ns=None, dummy=None): | ||
Ville M. Vainio
|
r1032 | """Activate the interactive interpreter. | ||
__call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start | ||||
the interpreter shell with the given local and global namespaces, and | ||||
optionally print a header string at startup. | ||||
The shell can be globally activated/deactivated using the | ||||
set/get_dummy_mode methods. This allows you to turn off a shell used | ||||
for debugging globally. | ||||
However, *each* time you call the shell you can override the current | ||||
state of dummy_mode with the optional keyword parameter 'dummy'. For | ||||
example, if you set dummy mode on with IPShell.set_dummy_mode(1), you | ||||
can still have a specific call work by making it as IPShell(dummy=0). | ||||
The optional keyword parameter dummy controls whether the call | ||||
Brian Granger
|
r2070 | actually does anything. | ||
""" | ||||
Ville M. Vainio
|
r1032 | |||
# If the user has turned it off, go away | ||||
if not self.IP.embedded_active: | ||||
return | ||||
# Normal exits from interactive mode set this flag, so the shell can't | ||||
# re-enter (it checks this variable at the start of interactive mode). | ||||
self.IP.exit_now = False | ||||
# Allow the dummy parameter to override the global __dummy_mode | ||||
if dummy or (dummy != 0 and self.__dummy_mode): | ||||
return | ||||
# Set global subsystems (display,completions) to our values | ||||
sys.displayhook = self.sys_displayhook_embed | ||||
if self.IP.has_readline: | ||||
self.IP.set_completer() | ||||
if self.banner and header: | ||||
format = '%s\n%s\n' | ||||
else: | ||||
format = '%s%s\n' | ||||
banner = format % (self.banner,header) | ||||
# Call the embedding code with a stack depth of 1 so it can skip over | ||||
# our call and get the original caller's namespaces. | ||||
self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1) | ||||
if self.exit_msg: | ||||
print self.exit_msg | ||||
# Restore global systems (display, completion) | ||||
sys.displayhook = self.sys_displayhook_ori | ||||
self.restore_system_completer() | ||||
Brian Granger
|
r2070 | def set_dummy_mode(self, dummy): | ||
Ville M. Vainio
|
r1032 | """Sets the embeddable shell's dummy mode parameter. | ||
set_dummy_mode(dummy): dummy = 0 or 1. | ||||
This parameter is persistent and makes calls to the embeddable shell | ||||
silently return without performing any action. This allows you to | ||||
globally activate or deactivate a shell you're using with a single call. | ||||
If you need to manually""" | ||||
if dummy not in [0,1,False,True]: | ||||
raise ValueError,'dummy parameter must be boolean' | ||||
self.__dummy_mode = dummy | ||||
def get_dummy_mode(self): | ||||
"""Return the current value of the dummy mode parameter. | ||||
""" | ||||
return self.__dummy_mode | ||||
Brian Granger
|
r2070 | def set_banner(self, banner): | ||
Ville M. Vainio
|
r1032 | """Sets the global banner. | ||
This banner gets prepended to every header printed when the shell | ||||
instance is called.""" | ||||
self.banner = banner | ||||
Brian Granger
|
r2070 | def set_exit_msg(self, exit_msg): | ||
Ville M. Vainio
|
r1032 | """Sets the global exit_msg. | ||
This exit message gets printed upon exiting every time the embedded | ||||
shell is called. It is None by default. """ | ||||
self.exit_msg = exit_msg | ||||
# This is the one which should be called by external code. | ||||
def start(user_ns = None): | ||||
Brian Granger
|
r2070 | """Return a running shell instance of :class:`IPShell`.""" | ||
return IPShell(user_ns = user_ns) | ||||
Ville M. Vainio
|
r1032 | |||