diff --git a/IPython/Shell.py b/IPython/Shell.py index 7f650ed..7bdd833 100644 --- a/IPython/Shell.py +++ b/IPython/Shell.py @@ -19,11 +19,24 @@ the new code in IPython.core.shell. from warnings import warn msg = """ -This module (IPython.Shell) has been moved to a new location -(IPython.core.shell) and is being refactored. Please update your code -to use the new IPython.core.shell module""" +This module (IPython.Shell) is deprecated. The classes that were in this +module have been replaced by: + +IPShell->IPython.core.iplib.InteractiveShell +IPShellEmbed->IPython.core.embed.InteractiveShellEmbed + +Please migrate your code to use these classes instead. +""" warn(msg, category=DeprecationWarning, stacklevel=1) -from IPython.core.shell import start, IPShell, IPShellEmbed +from IPython.core.iplib import InteractiveShell as IPShell +from IPython.core.embed import InteractiveShellEmbed as IPShellEmbed + +def start(user_ns=None, embedded=False): + """Return an instance of :class:`InteractiveShell`.""" + if embedded: + return InteractiveShellEmbed(user_ns=user_ns) + else: + return InteractiveShell(user_ns=user_ns) diff --git a/IPython/__init__.py b/IPython/__init__.py index f04897e..19caef8 100644 --- a/IPython/__init__.py +++ b/IPython/__init__.py @@ -34,9 +34,6 @@ if sys.version[0:3] < '2.4': # Therefore, non-IPython modules can be added to extensions directory sys.path.append(os.path.join(os.path.dirname(__file__), "extensions")) - -# from IPython.core import shell -# Shell = shell from IPython.core import iplib diff --git a/IPython/core/embed.py b/IPython/core/embed.py new file mode 100644 index 0000000..ccfb0a0 --- /dev/null +++ b/IPython/core/embed.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +An embedded IPython shell. + +Authors: + +* Brian Granger +* Fernando Perez + +Notes +----- +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import sys + +from IPython.core import ultratb +from IPython.core.iplib import InteractiveShell + +from IPython.utils.traitlets import Bool, Str +from IPython.utils.genutils import ask_yes_no + +#----------------------------------------------------------------------------- +# Classes and functions +#----------------------------------------------------------------------------- + +# This is an additional magic that is exposed in embedded shells. +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.embedded_active = False + print "This embedded IPython will not reactivate anymore once you exit." + + +class InteractiveShellEmbed(InteractiveShell): + + dummy_mode = Bool(False) + exit_msg = Str('') + + def __init__(self, parent=None, config=None, usage=None, + user_ns=None, user_global_ns=None, + banner1='', banner2='', + custom_exceptions=((),None), exit_msg=''): + + # First we need to save the state of sys.displayhook and + # sys.ipcompleter so we can restore it when we are done. + self.save_sys_displayhook() + self.save_sys_ipcompleter() + + super(InteractiveShellEmbed,self).__init__( + parent=parent, config=config, usage=usage, + user_ns=user_ns, user_global_ns=user_global_ns, + banner1=banner1, banner2=banner2, + custom_exceptions=custom_exceptions, embedded=True) + + self.save_sys_displayhook_embed() + self.exit_msg = exit_msg + self.define_magic("kill_embedded", kill_embedded) + + # don't use the ipython crash handler so that user exceptions aren't + # trapped + sys.excepthook = ultratb.FormattedTB(color_scheme = self.colors, + mode = self.xmode, + call_pdb = self.pdb) + + self.restore_sys_displayhook() + self.restore_sys_ipcompleter() + + def save_sys_displayhook(self): + # 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_orig = sys.displayhook + + def save_sys_ipcompleter(self): + """Save readline completer status.""" + try: + #print 'Save completer',sys.ipcompleter # dbg + self.sys_ipcompleter_orig = sys.ipcompleter + except: + pass # not nested with IPython + + def restore_sys_displayhook(self): + sys.displayhook = self.sys_displayhook_orig + + def restore_sys_ipcompleter(self): + """Restores the readline completer which was in place. + + This allows embedded IPython within IPython not to disrupt the + parent's completion. + """ + try: + self.readline.set_completer(self.sys_ipcompleter_orig) + sys.ipcompleter = self.sys_ipcompleter_orig + except: + pass + + def save_sys_displayhook_embed(self): + self.sys_displayhook_embed = sys.displayhook + + def restore_sys_displayhook_embed(self): + sys.displayhook = self.sys_displayhook_embed + + def __call__(self, header='', local_ns=None, global_ns=None, dummy=None): + """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 + actually does anything. + """ + + # If the user has turned it off, go away + if not self.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.exit_now = False + + # Allow the dummy parameter to override the global __dummy_mode + if dummy or (dummy != 0 and self.dummy_mode): + return + + self.restore_sys_displayhook_embed() + + if self.has_readline: + self.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.embed_mainloop(banner, local_ns, global_ns, stack_depth=1) + + if self.exit_msg: + print self.exit_msg + + # Restore global systems (display, completion) + self.restore_sys_displayhook() + self.restore_sys_ipcompleter() diff --git a/IPython/core/ipapi.py b/IPython/core/ipapi.py index 739ee14..f448613 100644 --- a/IPython/core/ipapi.py +++ b/IPython/core/ipapi.py @@ -29,20 +29,11 @@ Authors: from IPython.core.error import TryNext, UsageError from IPython.core.component import Component -from warnings import warn #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- -msg = """ -This module (IPython.core.ipapi) is being deprecated. For now, all we -offer here is the ``get`` function for getting the most recently created -InteractiveShell instance.""" - -warn(msg, category=DeprecationWarning, stacklevel=1) - - def get(): """Get the most recently created InteractiveShell instance.""" insts = Component.get_instances(name='__IP') @@ -50,7 +41,13 @@ def get(): for inst in insts[1:]: if inst.created > most_recent.created: most_recent = inst - return most_recent.getapi() + return most_recent + +def launch_new_instance(): + """Create a run a full blown IPython instance""" + from IPython.core.ipapp import IPythonApp + app = IPythonApp() + app.start() diff --git a/IPython/core/ipapp.py b/IPython/core/ipapp.py index a249447..155d36f 100644 --- a/IPython/core/ipapp.py +++ b/IPython/core/ipapp.py @@ -304,7 +304,6 @@ class IPythonApp(Application): # Create an InteractiveShell instance self.shell = InteractiveShell( - name='__IP', parent=None, config=self.master_config ) diff --git a/IPython/core/iplib.py b/IPython/core/iplib.py index b3b1712..46e283d 100644 --- a/IPython/core/iplib.py +++ b/IPython/core/iplib.py @@ -294,16 +294,16 @@ class InteractiveShell(Component, Magic): # Subclasses with thread support should override this as needed. isthreaded = False - def __init__(self, name, parent=None, config=None, usage=None, + def __init__(self, parent=None, config=None, usage=None, user_ns=None, user_global_ns=None, - banner1='', banner2='', + banner1=None, banner2=None, custom_exceptions=((),None), embedded=False): # This is where traitlets with a config_key argument are updated # from the values on config. # Ideally, from here on out, the config should only be used when # passing it to children components. - super(InteractiveShell, self).__init__(parent, config=config, name=name) + super(InteractiveShell, self).__init__(parent, config=config, name='__IP') self.init_instance_attrs() self.init_term_title() @@ -423,9 +423,9 @@ class InteractiveShell(Component, Magic): def init_banner(self, banner1, banner2): if self.c: # regular python doesn't print the banner with -c self.display_banner = False - if banner1: + if banner1 is not None: self.banner1 = banner1 - if banner2: + if banner2 is not None: self.banner2 = banner2 self.compute_banner() @@ -1066,10 +1066,10 @@ class InteractiveShell(Component, Magic): warn('help() not available - check site.py') def add_builtins(self): - """Store ipython references into the builtin namespace. + """Store ipython references into the __builtin__ namespace. - Some parts of ipython operate via builtins injected here, which hold a - reference to IPython itself.""" + We strive to modify the __builtin__ namespace as little as possible. + """ # Install our own quitter instead of the builtins. # This used to be in the __init__ method, but this is a better @@ -1088,25 +1088,7 @@ class InteractiveShell(Component, Magic): del deepreload except ImportError: pass - - # TODO: deprecate all of these, they are unsafe. Why though? - builtins_new = dict(__IPYTHON__ = self, - ip_set_hook = self.set_hook, - jobs = self.jobs, - # magic = self.magic, - ipalias = wrap_deprecated(self.ipalias), - # ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'), - ) - for biname,bival in builtins_new.items(): - try: - # store the orignal value so we can restore it - self.builtins_added[biname] = __builtin__.__dict__[biname] - except KeyError: - # or mark that it wasn't defined, and we'll just delete it at - # cleanup - self.builtins_added[biname] = Undefined - __builtin__.__dict__[biname] = bival - + # Keep in the builtins a flag for when IPython is active. We set it # with setdefault so that multiple nested IPythons don't clobber one # another. Each will increase its value by one upon being activated, diff --git a/IPython/core/shell.py b/IPython/core/shell.py deleted file mode 100644 index 8483199..0000000 --- a/IPython/core/shell.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -"""IPython Shell classes. - -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. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2009 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys - -from IPython.core import ultratb -from IPython.core import ipapi -from IPython.utils.genutils import ask_yes_no -from IPython.core.iplib import InteractiveShell -from IPython.core.ipmaker import make_IPython - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - - -class IPShell: - """Create an IPython instance. - - 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. - """ - - 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, - user_global_ns=user_global_ns, - debug=debug, shell_class=shell_class) - - def mainloop(self,sys_exit=0,banner=None): - self.IP.mainloop(banner) - if sys_exit: - sys.exit() - - -# This is an additional magic that is exposed in embedded shells. -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." - - -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. - - Usage (see also the example-embed.py file for a running example):: - - ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override]) - - * argv: list containing valid command-line options for IPython, as they - would appear in sys.argv[1:]. - - For example, the following command-line options:: - - $ ipython -prompt_in1 'Input <\\#>' -colors LightBG - - would be passed in the argv list as:: - - ['-prompt_in1','Input <\\#>','-colors','LightBG'] - - * banner: string which gets printed every time the interpreter starts. - - * exit_msg: string which gets printed every time the interpreter exits. - - * rc_override: a dict or Struct of configuration options such as those - 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). - - Then the ipshell instance can be called anywhere inside your code:: - - ipshell(header='') -> Opens up an IPython shell. - - * header: string printed by the IPython shell upon startup. This can let - 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 - on Dec. 06/01 concerning similar uses of pyrepl, and - by the IDL stop/continue commands. - """ - - def __init__(self, argv=None, banner='', exit_msg=None, - rc_override=None, user_ns=None): - """Note that argv here is a string, NOT a list.""" - - 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 = self.IP - ip.define_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 - sys.excepthook = ultratb.FormattedTB(color_scheme = self.IP.colors, - mode = self.IP.xmode, - call_pdb = self.IP.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 - - def __call__(self, header='', local_ns=None, global_ns=None, dummy=None): - """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 - actually does anything. - """ - - # 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() - - def set_dummy_mode(self, dummy): - """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 - - def set_banner(self, banner): - """Sets the global banner. - - This banner gets prepended to every header printed when the shell - instance is called.""" - - self.banner = banner - - def set_exit_msg(self, exit_msg): - """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): - """Return a running shell instance of :class:`IPShell`.""" - return IPShell(user_ns = user_ns) - diff --git a/IPython/ipapi.py b/IPython/ipapi.py index bfdbfdf..8a4dd65 100644 --- a/IPython/ipapi.py +++ b/IPython/ipapi.py @@ -25,5 +25,5 @@ to use the new IPython.core.ipapi module""" warn(msg, category=DeprecationWarning, stacklevel=1) -from IPython.core.ipapi import get +from IPython.core.ipapi import get, launch_new_instance diff --git a/IPython/scripts/ipython b/IPython/scripts/ipython index 2b1083f..a93e1de 100755 --- a/IPython/scripts/ipython +++ b/IPython/scripts/ipython @@ -23,7 +23,6 @@ this mode, there is no way to pass IPython any command-line options, as those are trapped first by Python itself. """ -import IPython.core.ipapp import IPythonApp +import IPython.core.ipapi import launch_new_instance -app = IPythonApp() -app.start() +launch_new_instance()