Browse files

Split generic part of terminal frontend/terminal/ipapp into core/shel…

…lapp

Now there's a class for IPKernel to inherit from in the qt code
  • Loading branch information...
1 parent d9bc319 commit 5c64f904ca5fa50e004cbd7b9c5ab45101310f8e @minrk committed Jun 3, 2011
Showing with 271 additions and 213 deletions.
  1. +10 −11 IPython/config/profile/default/ipython_config.py
  2. +243 −0 IPython/core/shellapp.py
  3. +18 −202 IPython/frontend/terminal/ipapp.py
View
21 IPython/config/profile/default/ipython_config.py
@@ -4,34 +4,33 @@
#-----------------------------------------------------------------------------
# Application-level options
#-----------------------------------------------------------------------------
-app = c.IPythonApp
-# app.display_banner = True
+# c.TerminalIPythonApp.display_banner = True
-# app.classic = False
+# c.TerminalIPythonApp.classic = False
-# app.nosep = True
+# c.TerminalIPythonApp.nosep = True
# If you still use multiple versions of IPytho on the same machine,
# set this to True to suppress warnings about old configuration files
-# app.ignore_old_config = False
+# c.TerminalIPythonApp.ignore_old_config = False
# Set this to determine the detail of what is logged at startup.
# The default is 30 and possible values are 0,10,20,30,40,50.
-# app.log_level = 20
+# c.Application.log_level = 20
# This should be a list of importable Python modules that have an
# load_ipython_extension(ip) method. This method gets called when the extension
# is loaded. You can put your extensions anywhere they can be imported
# but we add the extensions subdir of the ipython directory to sys.path
# during extension loading, so you can put them there as well.
-# app.extensions = [
+# c.InteractiveShellApp.extensions = [
# 'myextension'
# ]
# These lines are run in IPython in the user's namespace after extensions
# are loaded. They can contain full IPython syntax with magics etc.
-# app.exec_lines = [
+# c.InteractiveShellApp.exec_lines = [
# 'import numpy',
# 'a = 10; b = 20',
# '1/0'
@@ -41,7 +40,7 @@
# extension need to be pure Python. Files with a .ipy extension can have
# custom IPython syntax (like magics, etc.).
# These files need to be in the cwd, the ipython_dir or be absolute paths.
-# app.exec_files = [
+# c.InteractiveShellApp.exec_files = [
# 'mycode.py',
# 'fancy.ipy'
# ]
@@ -58,9 +57,9 @@
# c.InteractiveShell.automagic = False
-# c.TerminalTerminalInteractiveShell.banner1 = 'This if for overriding the default IPython banner'
+# c.TerminalInteractiveShell.banner1 = 'This if for overriding the default IPython banner'
-# c.TerminalTerminalInteractiveShell.banner2 = "This is for extra banner text"
+# c.TerminalInteractiveShell.banner2 = "This is for extra banner text"
# c.InteractiveShell.cache_size = 1000
View
243 IPython/core/shellapp.py
@@ -0,0 +1,243 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+A mixin for :class:`~IPython.core.newapplication.Application` classes that
+launch InteractiveShell instances, load extensions, etc.
+
+Authors
+-------
+
+* Min Ragan-Kelley
+"""
+
+#-----------------------------------------------------------------------------
+# Copyright (C) 2008-2011 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
+#-----------------------------------------------------------------------------
+
+from __future__ import absolute_import
+
+import os
+import sys
+
+from IPython.config.application import boolean_flag
+from IPython.config.configurable import Configurable
+from IPython.utils.path import filefind
+from IPython.utils.traitlets import Unicode, Instance, List
+
+#-----------------------------------------------------------------------------
+# Aliases and Flags
+#-----------------------------------------------------------------------------
+
+shell_flags = {}
+
+addflag = lambda *args: shell_flags.update(boolean_flag(*args))
+addflag('autoindent', 'InteractiveShell.autoindent',
+ 'Turn on autoindenting.', 'Turn off autoindenting.'
+)
+addflag('automagic', 'InteractiveShell.automagic',
+ """Turn on the auto calling of magic commands. Type %%magic at the
+ IPython prompt for more information.""",
+ 'Turn off the auto calling of magic commands.'
+)
+addflag('pdb', 'InteractiveShell.pdb',
+ "Enable auto calling the pdb debugger after every exception.",
+ "Disable auto calling the pdb debugger after every exception."
+)
+addflag('pprint', 'PlainTextFormatter.pprint',
+ "Enable auto pretty printing of results.",
+ "Disable auto auto pretty printing of results."
+)
+addflag('color-info', 'InteractiveShell.color_info',
+ """IPython can display information about objects via a set of func-
+ tions, and optionally can use colors for this, syntax highlighting
+ source code and various other elements. However, because this
+ information is passed through a pager (like 'less') and many pagers get
+ confused with color codes, this option is off by default. You can test
+ it and turn it on permanently in your ipython_config.py file if it
+ works for you. Test it and turn it on permanently if it works with
+ your system. The magic function %%color_info allows you to toggle this
+ inter- actively for testing.""",
+ "Disable using colors for info related things."
+)
+addflag('deep-reload', 'InteractiveShell.deep_reload',
+ """Enable deep (recursive) reloading by default. IPython can use the
+ deep_reload module which reloads changes in modules recursively (it
+ replaces the reload() function, so you don't need to change anything to
+ use it). deep_reload() forces a full reload of modules whose code may
+ have changed, which the default reload() function does not. When
+ deep_reload is off, IPython will use the normal reload(), but
+ deep_reload will still be available as dreload(). This feature is off
+ by default [which means that you have both normal reload() and
+ dreload()].""",
+ "Disable deep (recursive) reloading by default."
+)
+
+# it's possible we don't want short aliases for *all* of these:
+shell_aliases = dict(
+ autocall='InteractiveShell.autocall',
+ cache_size='InteractiveShell.cache_size',
+ colors='InteractiveShell.colors',
+ logfile='InteractiveShell.logfile',
+ log_append='InteractiveShell.logappend',
+ pi1='InteractiveShell.prompt_in1',
+ pi2='InteractiveShell.prompt_in1',
+ po='InteractiveShell.prompt_out',
+ si='InteractiveShell.separate_in',
+ so='InteractiveShell.separate_out',
+ so2='InteractiveShell.separate_out2',
+ xmode='InteractiveShell.xmode',
+ c='InteractiveShellApp.code_to_run',
+ ext='InteractiveShellApp.extra_extension',
+)
+
+#-----------------------------------------------------------------------------
+# Main classes and functions
+#-----------------------------------------------------------------------------
+
+class InteractiveShellApp(Configurable):
+ """A Mixin for applications that start InteractiveShell instances.
+
+ Provides configurables for loading extensions and executing files
+ as part of configuring a Shell environment.
+
+ Provides init_extensions() and init_code() methods, to be called
+ after init_shell(), which must be implemented by subclasses.
+ """
+ extensions = List(Unicode, config=True,
+ help="A list of dotted module names of IPython extensions to load."
+ )
+ extra_extension = Unicode('', config=True,
+ help="dotted module name of an IPython extension to load."
+ )
+ def _extra_extension_changed(self, name, old, new):
+ if new:
+ # add to self.extensions
+ self.extensions.append(new)
+
+ exec_files = List(Unicode, config=True,
+ help="""List of files to run at IPython startup."""
+ )
+ file_to_run = Unicode('', config=True,
+ help="""A file to be run""")
+
+ exec_lines = List(Unicode, config=True,
+ help="""lines of code to run at IPython startup."""
+ )
+ code_to_run = Unicode('', config=True,
+ help="Execute the given command string."
+ )
+ shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
+
+ def init_shell(self):
+ raise NotImplementedError("Override in subclasses")
+
+ def init_extensions(self):
+ """Load all IPython extensions in IPythonApp.extensions.
+
+ This uses the :meth:`ExtensionManager.load_extensions` to load all
+ the extensions listed in ``self.extensions``.
+ """
+ if not self.extensions:
+ return
+ try:
+ self.log.debug("Loading IPython extensions...")
+ extensions = self.extensions
+ for ext in extensions:
+ try:
+ self.log.info("Loading IPython extension: %s" % ext)
+ self.shell.extension_manager.load_extension(ext)
+ except:
+ self.log.warn("Error in loading extension: %s" % ext)
+ self.shell.showtraceback()
+ except:
+ self.log.warn("Unknown error in loading extensions:")
+ self.shell.showtraceback()
+
+ def init_code(self):
+ """run the pre-flight code, specified via exec_lines"""
+ self._run_exec_lines()
+ self._run_exec_files()
+ self._run_cmd_line_code()
+
+ def _run_exec_lines(self):
+ """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
+ if not self.exec_lines:
+ return
+ try:
+ self.log.debug("Running code from IPythonApp.exec_lines...")
+ for line in self.exec_lines:
+ try:
+ self.log.info("Running code in user namespace: %s" %
+ line)
+ self.shell.run_cell(line, store_history=False)
+ except:
+ self.log.warn("Error in executing line in user "
+ "namespace: %s" % line)
+ self.shell.showtraceback()
+ except:
+ self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
+ self.shell.showtraceback()
+
+ def _exec_file(self, fname):
+ full_filename = filefind(fname, [u'.', self.ipython_dir])
+ if os.path.isfile(full_filename):
+ if full_filename.endswith(u'.py'):
+ self.log.info("Running file in user namespace: %s" %
+ full_filename)
+ # Ensure that __file__ is always defined to match Python behavior
+ self.shell.user_ns['__file__'] = fname
+ try:
+ self.shell.safe_execfile(full_filename, self.shell.user_ns)
+ finally:
+ del self.shell.user_ns['__file__']
+ elif full_filename.endswith('.ipy'):
+ self.log.info("Running file in user namespace: %s" %
+ full_filename)
+ self.shell.safe_execfile_ipy(full_filename)
+ else:
+ self.log.warn("File does not have a .py or .ipy extension: <%s>"
+ % full_filename)
+
+ def _run_exec_files(self):
+ """Run files from IPythonApp.exec_files"""
+ if not self.exec_files:
+ return
+
+ self.log.debug("Running files in IPythonApp.exec_files...")
+ try:
+ for fname in self.exec_files:
+ self._exec_file(fname)
+ except:
+ self.log.warn("Unknown error in handling IPythonApp.exec_files:")
+ self.shell.showtraceback()
+
+ def _run_cmd_line_code(self):
+ """Run code or file specified at the command-line"""
+ if self.code_to_run:
+ line = self.code_to_run
+ try:
+ self.log.info("Running code given at command line (c=): %s" %
+ line)
+ self.shell.run_cell(line, store_history=False)
+ except:
+ self.log.warn("Error in executing line in user namespace: %s" %
+ line)
+ self.shell.showtraceback()
+
+ # Like Python itself, ignore the second if the first of these is present
+ elif self.file_to_run:
+ fname = self.file_to_run
+ try:
+ self._exec_file(fname)
+ except:
+ self.log.warn("Error in executing file in user namespace: %s" %
+ fname)
+ self.shell.showtraceback()
+
View
220 IPython/frontend/terminal/ipapp.py
@@ -40,11 +40,14 @@
from IPython.core.newapplication import (
ProfileDir, BaseIPythonApplication, base_flags, base_aliases
)
+from IPython.core.shellapp import (
+ InteractiveShellApp, shell_flags, shell_aliases
+)
from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
from IPython.lib import inputhook
-from IPython.utils.path import filefind, get_ipython_dir, check_for_old_config
+from IPython.utils.path import get_ipython_dir, check_for_old_config
from IPython.utils.traitlets import (
- Bool, Unicode, Dict, Instance, List,CaselessStrEnum
+ Bool, Dict, CaselessStrEnum
)
#-----------------------------------------------------------------------------
@@ -55,7 +58,6 @@
default_config_file_name = u'ipython_config.py'
-
#-----------------------------------------------------------------------------
# Crash handler for this application
#-----------------------------------------------------------------------------
@@ -119,69 +121,22 @@ def make_report(self,traceback):
# Aliases and Flags
#-----------------------------------------------------------------------------
flags = dict(base_flags)
-flags.update({
-
-
-})
+flags.update(shell_flags)
addflag = lambda *args: flags.update(boolean_flag(*args))
-addflag('autoindent', 'InteractiveShell.autoindent',
- 'Turn on autoindenting.', 'Turn off autoindenting.'
-)
-addflag('automagic', 'InteractiveShell.automagic',
- """Turn on the auto calling of magic commands. Type %%magic at the
- IPython prompt for more information.""",
- 'Turn off the auto calling of magic commands.'
-)
addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
'Turn on auto editing of files with syntax errors.',
'Turn off auto editing of files with syntax errors.'
)
-addflag('banner', 'IPythonApp.display_banner',
+addflag('banner', 'TerminalIPythonApp.display_banner',
"Display a banner upon starting IPython.",
"Don't display a banner upon starting IPython."
)
-addflag('pdb', 'InteractiveShell.pdb',
- "Enable auto calling the pdb debugger after every exception.",
- "Disable auto calling the pdb debugger after every exception."
-)
-addflag('pprint', 'PlainTextFormatter.pprint',
- "Enable auto pretty printing of results.",
- "Disable auto auto pretty printing of results."
-)
-addflag('color-info', 'InteractiveShell.color_info',
- """IPython can display information about objects via a set of func-
- tions, and optionally can use colors for this, syntax highlighting
- source code and various other elements. However, because this
- information is passed through a pager (like 'less') and many pagers get
- confused with color codes, this option is off by default. You can test
- it and turn it on permanently in your ipython_config.py file if it
- works for you. Test it and turn it on permanently if it works with
- your system. The magic function %%color_info allows you to toggle this
- inter- actively for testing.""",
- "Disable using colors for info related things."
-)
addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
"""Set to confirm when you try to exit IPython with an EOF (Control-D
in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
you can force a direct exit without any confirmation.""",
"Don't prompt the user when exiting."
)
-addflag('deep-reload', 'InteractiveShell.deep_reload',
- """Enable deep (recursive) reloading by default. IPython can use the
- deep_reload module which reloads changes in modules recursively (it
- replaces the reload() function, so you don't need to change anything to
- use it). deep_reload() forces a full reload of modules whose code may
- have changed, which the default reload() function does not. When
- deep_reload is off, IPython will use the normal reload(), but
- deep_reload will still be available as dreload(). This feature is off
- by default [which means that you have both normal reload() and
- dreload()].""",
- "Disable deep (recursive) reloading by default."
-)
-addflag('readline', 'InteractiveShell.readline_use',
- "Enable readline for command line usage.",
- "Disable readline for command line usage."
-)
addflag('term-title', 'TerminalInteractiveShell.term_title',
"Enable auto setting the terminal title.",
"Disable auto setting the terminal title."
@@ -209,7 +164,7 @@ def make_report(self,traceback):
#
# # quick is harder to implement
flags['quick']=(
- {'IPythonApp' : {'quick' : True}},
+ {'TerminalIPythonApp' : {'quick' : True}},
"Enable quick startup with no config files."
)
@@ -221,52 +176,39 @@ def make_report(self,traceback):
flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
flags['i'] = (
- {'IPythonApp' : {'force_interact' : True}},
+ {'TerminalIPythonApp' : {'force_interact' : True}},
"If running code from the command line, become interactive afterwards."
)
flags['pylab'] = (
- {'IPythonApp' : {'pylab' : 'auto'}},
+ {'TerminalIPythonApp' : {'pylab' : 'auto'}},
"""Pre-load matplotlib and numpy for interactive use with
the default matplotlib backend."""
)
aliases = dict(base_aliases)
+aliases.update(shell_aliases)
# it's possible we don't want short aliases for *all* of these:
aliases.update(dict(
- autocall='InteractiveShell.autocall',
- cache_size='InteractiveShell.cache_size',
- colors='InteractiveShell.colors',
editor='TerminalInteractiveShell.editor',
- logfile='InteractiveShell.logfile',
- log_append='InteractiveShell.logappend',
- pi1='InteractiveShell.prompt_in1',
- pi2='InteractiveShell.prompt_in1',
- po='InteractiveShell.prompt_out',
sl='TerminalInteractiveShell.screen_length',
- si='InteractiveShell.separate_in',
- so='InteractiveShell.separate_out',
- so2='InteractiveShell.separate_out2',
- xmode='InteractiveShell.xmode',
- c='IPythonApp.code_to_run',
- ext='IPythonApp.extra_extension',
- gui='IPythonApp.gui',
- pylab='IPythonApp.pylab',
+ gui='TerminalIPythonApp.gui',
+ pylab='TerminalIPythonApp.pylab',
))
#-----------------------------------------------------------------------------
# Main classes and functions
#-----------------------------------------------------------------------------
-class IPythonApp(BaseIPythonApplication):
+class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
name = u'ipython'
description = usage.cl_usage
# command_line_loader = IPAppConfigLoader
default_config_file_name = default_config_file_name
crash_handler_class = IPAppCrashHandler
flags = Dict(flags)
aliases = Dict(aliases)
- classes = [TerminalInteractiveShell, ProfileDir, PlainTextFormatter]
+ classes = [InteractiveShellApp, TerminalInteractiveShell, ProfileDir, PlainTextFormatter]
# *do* autocreate requested profile
auto_create=Bool(True)
copy_config_files=Bool(True)
@@ -294,16 +236,6 @@ def _quick_changed(self, name, old, new):
display_banner = Bool(True, config=True,
help="Whether to display a banner upon starting IPython."
)
- extensions = List(Unicode, config=True,
- help="A list of dotted module names of IPython extensions to load."
- )
- extra_extension = Unicode('', config=True,
- help="dotted module name of an IPython extension to load."
- )
- def _extra_extension_changed(self, name, old, new):
- if new:
- # add to self.extensions
- self.extensions.append(new)
# if there is code of files to run from the cmd line, don't interact
# unless the --i flag (App.force_interact) is true.
@@ -314,22 +246,10 @@ def _extra_extension_changed(self, name, old, new):
def _force_interact_changed(self, name, old, new):
if new:
self.interact = True
-
- exec_files = List(Unicode, config=True,
- help="""List of files to run at IPython startup."""
- )
- file_to_run = Unicode('', config=True,
- help="""A file to be run""")
+
def _file_to_run_changed(self, name, old, new):
if new and not self.force_interact:
self.interact = False
-
- exec_lines = List(Unicode, config=True,
- help="""lines of code to run at IPython startup."""
- )
- code_to_run = Unicode('', config=True,
- help="Execute the given command string."
- )
_code_to_run_changed = _file_to_run_changed
# internal, not-configurable
@@ -338,7 +258,7 @@ def _file_to_run_changed(self, name, old, new):
def initialize(self, argv=None):
"""Do actions after construct, but before starting the app."""
- super(IPythonApp, self).initialize(argv)
+ super(TerminalIPythonApp, self).initialize(argv)
if not self.ignore_old_config:
check_for_old_config(self.ipython_dir)
@@ -401,110 +321,6 @@ def init_gui_pylab(self):
self.log.warn("Error in enabling GUI event loop integration:")
self.shell.showtraceback()
- def init_extensions(self):
- """Load all IPython extensions in IPythonApp.extensions.
-
- This uses the :meth:`ExtensionManager.load_extensions` to load all
- the extensions listed in ``self.extensions``.
- """
- if not self.extensions:
- return
- try:
- self.log.debug("Loading IPython extensions...")
- extensions = self.extensions
- for ext in extensions:
- try:
- self.log.info("Loading IPython extension: %s" % ext)
- self.shell.extension_manager.load_extension(ext)
- except:
- self.log.warn("Error in loading extension: %s" % ext)
- self.shell.showtraceback()
- except:
- self.log.warn("Unknown error in loading extensions:")
- self.shell.showtraceback()
-
- def init_code(self):
- """run the pre-flight code, specified via exec_lines"""
- self._run_exec_lines()
- self._run_exec_files()
- self._run_cmd_line_code()
-
- def _run_exec_lines(self):
- """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
- if not self.exec_lines:
- return
- try:
- self.log.debug("Running code from IPythonApp.exec_lines...")
- for line in self.exec_lines:
- try:
- self.log.info("Running code in user namespace: %s" %
- line)
- self.shell.run_cell(line, store_history=False)
- except:
- self.log.warn("Error in executing line in user "
- "namespace: %s" % line)
- self.shell.showtraceback()
- except:
- self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
- self.shell.showtraceback()
-
- def _exec_file(self, fname):
- full_filename = filefind(fname, [u'.', self.ipython_dir])
- if os.path.isfile(full_filename):
- if full_filename.endswith(u'.py'):
- self.log.info("Running file in user namespace: %s" %
- full_filename)
- # Ensure that __file__ is always defined to match Python behavior
- self.shell.user_ns['__file__'] = fname
- try:
- self.shell.safe_execfile(full_filename, self.shell.user_ns)
- finally:
- del self.shell.user_ns['__file__']
- elif full_filename.endswith('.ipy'):
- self.log.info("Running file in user namespace: %s" %
- full_filename)
- self.shell.safe_execfile_ipy(full_filename)
- else:
- self.log.warn("File does not have a .py or .ipy extension: <%s>"
- % full_filename)
-
- def _run_exec_files(self):
- """Run files from IPythonApp.exec_files"""
- if not self.exec_files:
- return
-
- self.log.debug("Running files in IPythonApp.exec_files...")
- try:
- for fname in self.exec_files:
- self._exec_file(fname)
- except:
- self.log.warn("Unknown error in handling IPythonApp.exec_files:")
- self.shell.showtraceback()
-
- def _run_cmd_line_code(self):
- """Run code or file specified at the command-line"""
- if self.code_to_run:
- line = self.code_to_run
- try:
- self.log.info("Running code given at command line (c=): %s" %
- line)
- self.shell.run_cell(line, store_history=False)
- except:
- self.log.warn("Error in executing line in user namespace: %s" %
- line)
- self.shell.showtraceback()
-
- # Like Python itself, ignore the second if the first of these is present
- elif self.file_to_run:
- fname = self.file_to_run
- try:
- self._exec_file(fname)
- except:
- self.log.warn("Error in executing file in user namespace: %s" %
- fname)
- self.shell.showtraceback()
-
-
def start(self):
# perform any prexec steps:
if self.interact:
@@ -529,7 +345,7 @@ def load_default_config(ipython_dir=None):
def launch_new_instance():
"""Create and run a full blown IPython instance"""
- app = IPythonApp()
+ app = TerminalIPythonApp()
app.initialize()
# print app.config
# print app.profile_dir.location

0 comments on commit 5c64f90

Please sign in to comment.