From c9ef4c7627401a2cd460f5f99a4af729924a1a46 2011-06-20 23:39:15 From: MinRK <benjaminrk@gmail.com> Date: 2011-06-20 23:39:15 Subject: [PATCH] Terminal IPython working with newapp --- diff --git a/IPython/core/history.py b/IPython/core/history.py index 62720e4..723b150 100644 --- a/IPython/core/history.py +++ b/IPython/core/history.py @@ -101,18 +101,15 @@ class HistoryManager(Configurable): if self.hist_file == u'': # No one has set the hist_file, yet. - if shell.profile: - histfname = 'history-%s' % shell.profile - else: - histfname = 'history' - self.hist_file = os.path.join(shell.ipython_dir, histfname + '.sqlite') + histfname = 'history' + self.hist_file = os.path.join(shell.profile_dir.location, histfname + '.sqlite') try: self.init_db() except sqlite3.DatabaseError: if os.path.isfile(self.hist_file): # Try to move the file out of the way. - newpath = os.path.join(self.shell.ipython_dir, "hist-corrupt.sqlite") + newpath = os.path.join(self.shell.profile_dir.location, "hist-corrupt.sqlite") os.rename(self.hist_file, newpath) print("ERROR! History file wasn't a valid SQLite database.", "It was moved to %s" % newpath, "and a new file created.") diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index e32d32c..93ca390 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -54,6 +54,7 @@ from IPython.core.inputsplitter import IPythonInputSplitter from IPython.core.logger import Logger from IPython.core.macro import Macro from IPython.core.magic import Magic +from IPython.core.newapplication import ProfileDir from IPython.core.payload import PayloadManager from IPython.core.plugin import PluginManager from IPython.core.prefilter import PrefilterManager, ESC_MAGIC @@ -238,7 +239,9 @@ class InteractiveShell(SingletonConfigurable, Magic): """ ) colors = CaselessStrEnum(('NoColor','LightBG','Linux'), - default_value=get_default_colors(), config=True) + default_value=get_default_colors(), config=True, + help="Set the color scheme (NoColor, Linux, and LightBG)." + ) debug = CBool(False, config=True) deep_reload = CBool(False, config=True, help= """ @@ -291,7 +294,6 @@ class InteractiveShell(SingletonConfigurable, Magic): """ ) - profile = Unicode('', config=True) prompt_in1 = Str('In [\\#]: ', config=True) prompt_in2 = Str(' .\\D.: ', config=True) prompt_out = Str('Out[\\#]: ', config=True) @@ -342,10 +344,18 @@ class InteractiveShell(SingletonConfigurable, Magic): payload_manager = Instance('IPython.core.payload.PayloadManager') history_manager = Instance('IPython.core.history.HistoryManager') + profile_dir = Instance('IPython.core.newapplication.ProfileDir') + @property + def profile(self): + if self.profile_dir is not None: + name = os.path.basename(self.profile_dir.location) + return name.replace('profile_','') + + # Private interface _post_execute = Instance(dict) - def __init__(self, config=None, ipython_dir=None, + def __init__(self, config=None, ipython_dir=None, profile_dir=None, user_ns=None, user_global_ns=None, custom_exceptions=((), None)): @@ -355,6 +365,7 @@ class InteractiveShell(SingletonConfigurable, Magic): # These are relatively independent and stateless self.init_ipython_dir(ipython_dir) + self.init_profile_dir(profile_dir) self.init_instance_attrs() self.init_environment() @@ -372,7 +383,7 @@ class InteractiveShell(SingletonConfigurable, Magic): # While we're trying to have each part of the code directly access what # it needs without keeping redundant references to objects, we have too # much legacy code that expects ip.db to exist. - self.db = PickleShareDB(os.path.join(self.ipython_dir, 'db')) + self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db')) self.init_history() self.init_encoding() @@ -457,16 +468,16 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_ipython_dir(self, ipython_dir): if ipython_dir is not None: self.ipython_dir = ipython_dir - self.config.Global.ipython_dir = self.ipython_dir return - if hasattr(self.config.Global, 'ipython_dir'): - self.ipython_dir = self.config.Global.ipython_dir - else: - self.ipython_dir = get_ipython_dir() + self.ipython_dir = get_ipython_dir() - # All children can just read this - self.config.Global.ipython_dir = self.ipython_dir + def init_profile_dir(self, profile_dir): + if profile_dir is not None: + self.profile_dir = profile_dir + return + self.profile_dir =\ + ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default') def init_instance_attrs(self): self.more = False diff --git a/IPython/core/magic.py b/IPython/core/magic.py index d904d28..5399aa2 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -46,6 +46,7 @@ from IPython.core import debugger, oinspect from IPython.core.error import TryNext from IPython.core.error import UsageError from IPython.core.fakemodule import FakeModule +from IPython.core.newapplication import ProfileDir from IPython.core.macro import Macro from IPython.core import page from IPython.core.prefilter import ESC_MAGIC @@ -533,10 +534,7 @@ Currently the magic system has the following functions:\n""" def magic_profile(self, parameter_s=''): """Print your currently active IPython profile.""" - if self.shell.profile: - printpl('Current IPython profile: $self.shell.profile.') - else: - print 'No profile active.' + print self.shell.profile def magic_pinfo(self, parameter_s='', namespaces=None): """Provide detailed information about an object. @@ -3373,22 +3371,16 @@ Defaulting color scheme to 'NoColor'""" else: overwrite = False from IPython.config import profile - profile_dir = os.path.split(profile.__file__)[0] + profile_dir = os.path.dirname(profile.__file__) ipython_dir = self.ipython_dir - files = os.listdir(profile_dir) - - to_install = [] - for f in files: - if f.startswith('ipython_config'): - src = os.path.join(profile_dir, f) - dst = os.path.join(ipython_dir, f) - if (not os.path.isfile(dst)) or overwrite: - to_install.append((f, src, dst)) - if len(to_install)>0: - print "Installing profiles to: ", ipython_dir - for (f, src, dst) in to_install: - shutil.copy(src, dst) - print " %s" % f + print "Installing profiles to: %s [overwrite=%s]"(ipython_dir,overwrite) + for src in os.listdir(profile_dir): + if src.startswith('profile_'): + name = src.replace('profile_', '') + print " %s"%name + pd = ProfileDir.create_profile_dir_by_name(ipython_dir, name) + pd.copy_config_file('ipython_config.py', path=src, + overwrite=overwrite) @skip_doctest def magic_install_default_config(self, s): @@ -3404,15 +3396,9 @@ Defaulting color scheme to 'NoColor'""" overwrite = True else: overwrite = False - from IPython.config import default - config_dir = os.path.split(default.__file__)[0] - ipython_dir = self.ipython_dir - default_config_file_name = 'ipython_config.py' - src = os.path.join(config_dir, default_config_file_name) - dst = os.path.join(ipython_dir, default_config_file_name) - if (not os.path.isfile(dst)) or overwrite: - shutil.copy(src, dst) - print "Installing default config file: %s" % dst + pd = self.shell.profile_dir + print "Installing default config file in: %s" % pd.location + pd.copy_config_file('ipython_config.py', overwrite=overwrite) # Pylab support: simple wrappers that activate pylab, load gui input # handling and modify slightly %run diff --git a/IPython/frontend/terminal/interactiveshell.py b/IPython/frontend/terminal/interactiveshell.py index ede323c..d27ea2e 100644 --- a/IPython/frontend/terminal/interactiveshell.py +++ b/IPython/frontend/terminal/interactiveshell.py @@ -58,11 +58,21 @@ raw_input_original = raw_input class TerminalInteractiveShell(InteractiveShell): - autoedit_syntax = CBool(False, config=True) + autoedit_syntax = CBool(False, config=True, + help="auto editing of files with syntax errors.") banner = Unicode('') - banner1 = Unicode(default_banner, config=True) - banner2 = Unicode('', config=True) - confirm_exit = CBool(True, config=True) + banner1 = Unicode(default_banner, config=True, + help="""The part of the banner to be printed before the profile""" + ) + banner2 = Unicode('', config=True, + help="""The part of the banner to be printed after the profile""" + ) + confirm_exit = CBool(True, config=True, + help=""" + Set to confirm when you try to exit IPython with an EOF (Control-D + in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or + '%%Exit', you can force a direct exit without any confirmation.""", + ) # This display_banner only controls whether or not self.show_banner() # is called when mainloop/interact are called. The default is False # because for the terminal based application, the banner behavior @@ -71,19 +81,35 @@ class TerminalInteractiveShell(InteractiveShell): display_banner = CBool(False) # This isn't configurable! embedded = CBool(False) embedded_active = CBool(False) - editor = Unicode(get_default_editor(), config=True) - pager = Unicode('less', config=True) - - screen_length = Int(0, config=True) - term_title = CBool(False, config=True) - - def __init__(self, config=None, ipython_dir=None, user_ns=None, + editor = Unicode(get_default_editor(), config=True, + help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." + ) + pager = Unicode('less', config=True, + help="The shell program to be used for paging.") + + screen_length = Int(0, config=True, + help= + """Number of lines of your screen, used to control printing of very + long strings. Strings longer than this number of lines will be sent + through a pager instead of directly printed. The default value for + this is 0, which means IPython will auto-detect your screen size every + time it needs to print certain potentially long strings (this doesn't + change the behavior of the 'print' keyword, it's only triggered + internally). If for some reason this isn't working well (it needs + curses support), specify it yourself. Otherwise don't change the + default.""", + ) + term_title = CBool(False, config=True, + help="Enable auto setting the terminal title." + ) + + def __init__(self, config=None, ipython_dir=None, profile_dir=None, user_ns=None, user_global_ns=None, custom_exceptions=((),None), usage=None, banner1=None, banner2=None, display_banner=None): super(TerminalInteractiveShell, self).__init__( - config=config, ipython_dir=ipython_dir, user_ns=user_ns, + config=config, profile_dir=profile_dir, user_ns=user_ns, user_global_ns=user_global_ns, custom_exceptions=custom_exceptions ) # use os.system instead of utils.process.system by default, except on Windows diff --git a/IPython/frontend/terminal/ipapp.py b/IPython/frontend/terminal/ipapp.py index c667181..99fa337 100755 --- a/IPython/frontend/terminal/ipapp.py +++ b/IPython/frontend/terminal/ipapp.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # encoding: utf-8 """ -The :class:`~IPython.core.application.Application` object for the command +The :class:`~IPython.core.newapplication.Application` object for the command line :command:`ipython` program. Authors @@ -9,6 +9,7 @@ Authors * Brian Granger * Fernando Perez +* Min Ragan-Kelley """ #----------------------------------------------------------------------------- @@ -28,17 +29,23 @@ import logging import os import sys +from IPython.config.loader import ( + Config, PyFileConfigLoader +) +from IPython.config.application import boolean_flag from IPython.core import release +from IPython.core import usage from IPython.core.crashhandler import CrashHandler -from IPython.core.application import Application, BaseAppConfigLoader -from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell -from IPython.config.loader import ( - Config, - PyFileConfigLoader +from IPython.core.formatters import PlainTextFormatter +from IPython.core.newapplication import ( + ProfileDir, BaseIPythonApplication, base_flags, base_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.core import usage +from IPython.utils.traitlets import ( + Bool, Unicode, Dict, Instance, List,CaselessStrEnum +) #----------------------------------------------------------------------------- # Globals, utilities and helpers @@ -48,275 +55,6 @@ from IPython.core import usage default_config_file_name = u'ipython_config.py' -class IPAppConfigLoader(BaseAppConfigLoader): - - def _add_arguments(self): - super(IPAppConfigLoader, self)._add_arguments() - paa = self.parser.add_argument - paa('-p', - '--profile', dest='Global.profile', type=unicode, - help= - """The string name of the ipython profile to be used. Assume that your - config file is ipython_config-<name>.py (looks in current dir first, - then in IPYTHON_DIR). This is a quick way to keep and load multiple - config files for different tasks, especially if include your basic one - in your more specialized ones. You can keep a basic - IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which - include this one and load extra things for particular tasks.""", - metavar='Global.profile') - paa('--config-file', - dest='Global.config_file', type=unicode, - help= - """Set the config file name to override default. Normally IPython - loads ipython_config.py (from current directory) or - IPYTHON_DIR/ipython_config.py. If the loading of your config file - fails, IPython starts with a bare bones configuration (no modules - loaded at all).""", - metavar='Global.config_file') - paa('--autocall', - dest='InteractiveShell.autocall', type=int, - help= - """Make IPython automatically call any callable object even if you - didn't type explicit parentheses. For example, 'str 43' becomes - 'str(43)' automatically. The value can be '0' to disable the feature, - '1' for 'smart' autocall, where it is not applied if there are no more - arguments on the line, and '2' for 'full' autocall, where all callable - objects are automatically called (even if no arguments are present). - The default is '1'.""", - metavar='InteractiveShell.autocall') - paa('--autoindent', - action='store_true', dest='InteractiveShell.autoindent', - help='Turn on autoindenting.') - paa('--no-autoindent', - action='store_false', dest='InteractiveShell.autoindent', - help='Turn off autoindenting.') - paa('--automagic', - action='store_true', dest='InteractiveShell.automagic', - help= - """Turn on the auto calling of magic commands. Type %%magic at the - IPython prompt for more information.""") - paa('--no-automagic', - action='store_false', dest='InteractiveShell.automagic', - help='Turn off the auto calling of magic commands.') - paa('--autoedit-syntax', - action='store_true', dest='TerminalInteractiveShell.autoedit_syntax', - help='Turn on auto editing of files with syntax errors.') - paa('--no-autoedit-syntax', - action='store_false', dest='TerminalInteractiveShell.autoedit_syntax', - help='Turn off auto editing of files with syntax errors.') - paa('--banner', - action='store_true', dest='Global.display_banner', - help='Display a banner upon starting IPython.') - paa('--no-banner', - action='store_false', dest='Global.display_banner', - help="Don't display a banner upon starting IPython.") - paa('--cache-size', - type=int, dest='InteractiveShell.cache_size', - help= - """Set the size of the output cache. The default is 1000, you can - change it permanently in your config file. Setting it to 0 completely - disables the caching system, and the minimum value accepted is 20 (if - you provide a value less than 20, it is reset to 0 and a warning is - issued). This limit is defined because otherwise you'll spend more - time re-flushing a too small cache than working""", - metavar='InteractiveShell.cache_size') - paa('--classic', - action='store_true', dest='Global.classic', - help="Gives IPython a similar feel to the classic Python prompt.") - paa('--colors', - type=str, dest='InteractiveShell.colors', - help="Set the color scheme (NoColor, Linux, and LightBG).", - metavar='InteractiveShell.colors') - paa('--color-info', - action='store_true', dest='InteractiveShell.color_info', - help= - """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.""") - paa('--no-color-info', - action='store_false', dest='InteractiveShell.color_info', - help="Disable using colors for info related things.") - paa('--confirm-exit', - action='store_true', dest='TerminalInteractiveShell.confirm_exit', - help= - """Set to confirm when you try to exit IPython with an EOF (Control-D - in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or - '%%Exit', you can force a direct exit without any confirmation.""") - paa('--no-confirm-exit', - action='store_false', dest='TerminalInteractiveShell.confirm_exit', - help="Don't prompt the user when exiting.") - paa('--deep-reload', - action='store_true', dest='InteractiveShell.deep_reload', - help= - """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 fea- ture is off - by default [which means that you have both normal reload() and - dreload()].""") - paa('--no-deep-reload', - action='store_false', dest='InteractiveShell.deep_reload', - help="Disable deep (recursive) reloading by default.") - paa('--editor', - type=str, dest='TerminalInteractiveShell.editor', - help="Set the editor used by IPython (default to $EDITOR/vi/notepad).", - metavar='TerminalInteractiveShell.editor') - paa('--log','-l', - action='store_true', dest='InteractiveShell.logstart', - help="Start logging to the default log file (./ipython_log.py).") - paa('--logfile','-lf', - type=unicode, dest='InteractiveShell.logfile', - help="Start logging to logfile with this name.", - metavar='InteractiveShell.logfile') - paa('--log-append','-la', - type=unicode, dest='InteractiveShell.logappend', - help="Start logging to the given file in append mode.", - metavar='InteractiveShell.logfile') - paa('--pdb', - action='store_true', dest='InteractiveShell.pdb', - help="Enable auto calling the pdb debugger after every exception.") - paa('--no-pdb', - action='store_false', dest='InteractiveShell.pdb', - help="Disable auto calling the pdb debugger after every exception.") - paa('--pprint', - action='store_true', dest='PlainTextFormatter.pprint', - help="Enable auto pretty printing of results.") - paa('--no-pprint', - action='store_false', dest='PlainTextFormatter.pprint', - help="Disable auto auto pretty printing of results.") - paa('--prompt-in1','-pi1', - type=str, dest='InteractiveShell.prompt_in1', - help= - """Set the main input prompt ('In [\#]: '). Note that if you are using - numbered prompts, the number is represented with a '\#' in the string. - Don't forget to quote strings with spaces embedded in them. Most - bash-like escapes can be used to customize IPython's prompts, as well - as a few additional ones which are IPython-spe- cific. All valid - prompt escapes are described in detail in the Customization section of - the IPython manual.""", - metavar='InteractiveShell.prompt_in1') - paa('--prompt-in2','-pi2', - type=str, dest='InteractiveShell.prompt_in2', - help= - """Set the secondary input prompt (' .\D.: '). Similar to the previous - option, but used for the continuation prompts. The special sequence - '\D' is similar to '\#', but with all digits replaced by dots (so you - can have your continuation prompt aligned with your input prompt). - Default: ' .\D.: ' (note three spaces at the start for alignment with - 'In [\#]')""", - metavar='InteractiveShell.prompt_in2') - paa('--prompt-out','-po', - type=str, dest='InteractiveShell.prompt_out', - help="Set the output prompt ('Out[\#]:')", - metavar='InteractiveShell.prompt_out') - paa('--quick', - action='store_true', dest='Global.quick', - help="Enable quick startup with no config files.") - paa('--readline', - action='store_true', dest='InteractiveShell.readline_use', - help="Enable readline for command line usage.") - paa('--no-readline', - action='store_false', dest='InteractiveShell.readline_use', - help="Disable readline for command line usage.") - paa('--screen-length','-sl', - type=int, dest='TerminalInteractiveShell.screen_length', - help= - """Number of lines of your screen, used to control printing of very - long strings. Strings longer than this number of lines will be sent - through a pager instead of directly printed. The default value for - this is 0, which means IPython will auto-detect your screen size every - time it needs to print certain potentially long strings (this doesn't - change the behavior of the 'print' keyword, it's only triggered - internally). If for some reason this isn't working well (it needs - curses support), specify it yourself. Otherwise don't change the - default.""", - metavar='TerminalInteractiveShell.screen_length') - paa('--separate-in','-si', - type=str, dest='InteractiveShell.separate_in', - help="Separator before input prompts. Default '\\n'.", - metavar='InteractiveShell.separate_in') - paa('--separate-out','-so', - type=str, dest='InteractiveShell.separate_out', - help="Separator before output prompts. Default 0 (nothing).", - metavar='InteractiveShell.separate_out') - paa('--separate-out2','-so2', - type=str, dest='InteractiveShell.separate_out2', - help="Separator after output prompts. Default 0 (nonight).", - metavar='InteractiveShell.separate_out2') - paa('--no-sep', - action='store_true', dest='Global.nosep', - help="Eliminate all spacing between prompts.") - paa('--term-title', - action='store_true', dest='TerminalInteractiveShell.term_title', - help="Enable auto setting the terminal title.") - paa('--no-term-title', - action='store_false', dest='TerminalInteractiveShell.term_title', - help="Disable auto setting the terminal title.") - paa('--xmode', - type=str, dest='InteractiveShell.xmode', - help= - """Exception reporting mode ('Plain','Context','Verbose'). Plain: - similar to python's normal traceback printing. Context: prints 5 lines - of context source code around each line in the traceback. Verbose: - similar to Context, but additionally prints the variables currently - visible where the exception happened (shortening their strings if too - long). This can potentially be very slow, if you happen to have a huge - data structure whose string representation is complex to compute. - Your computer may appear to freeze for a while with cpu usage at 100%%. - If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting - it more than once). - """, - metavar='InteractiveShell.xmode') - paa('--ext', - type=str, dest='Global.extra_extension', - help="The dotted module name of an IPython extension to load.", - metavar='Global.extra_extension') - paa('-c', - type=str, dest='Global.code_to_run', - help="Execute the given command string.", - metavar='Global.code_to_run') - paa('-i', - action='store_true', dest='Global.force_interact', - help= - "If running code from the command line, become interactive afterwards.") - - # Options to start with GUI control enabled from the beginning - paa('--gui', - type=str, dest='Global.gui', - help="Enable GUI event loop integration ('qt', 'wx', 'gtk').", - metavar='gui-mode') - paa('--pylab','-pylab', - type=str, dest='Global.pylab', - nargs='?', const='auto', metavar='gui-mode', - help="Pre-load matplotlib and numpy for interactive use. "+ - "If no value is given, the gui backend is matplotlib's, else use "+ - "one of: ['tk', 'qt', 'wx', 'gtk', 'osx'].") - - # Legacy GUI options. Leave them in for backwards compatibility, but the - # 'thread' names are really a misnomer now. - paa('--wthread', '-wthread', - action='store_true', dest='Global.wthread', - help= - """Enable wxPython event loop integration. (DEPRECATED, use --gui wx)""") - paa('--q4thread', '--qthread', '-q4thread', '-qthread', - action='store_true', dest='Global.q4thread', - help= - """Enable Qt4 event loop integration. Qt3 is no longer supported. - (DEPRECATED, use --gui qt)""") - paa('--gthread', '-gthread', - action='store_true', dest='Global.gthread', - help= - """Enable GTK event loop integration. (DEPRECATED, use --gui gtk)""") - #----------------------------------------------------------------------------- # Crash handler for this application @@ -377,206 +115,337 @@ class IPAppCrashHandler(CrashHandler): return ''.join(report) +#----------------------------------------------------------------------------- +# Aliases and Flags +#----------------------------------------------------------------------------- +flags = dict(base_flags) +flags.update({ + + +}) +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', + "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', 'quit' or + '%%Exit', 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 fea- ture 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." +) +classic_config = Config() +classic_config.InteractiveShell.cache_size = 0 +classic_config.PlainTextFormatter.pprint = False +classic_config.InteractiveShell.prompt_in1 = '>>> ' +classic_config.InteractiveShell.prompt_in2 = '... ' +classic_config.InteractiveShell.prompt_out = '' +classic_config.InteractiveShell.separate_in = '' +classic_config.InteractiveShell.separate_out = '' +classic_config.InteractiveShell.separate_out2 = '' +classic_config.InteractiveShell.colors = 'NoColor' +classic_config.InteractiveShell.xmode = 'Plain' + +flags['classic']=( + classic_config, + "Gives IPython a similar feel to the classic Python prompt." +) +# # log doesn't make so much sense this way anymore +# paa('--log','-l', +# action='store_true', dest='InteractiveShell.logstart', +# help="Start logging to the default log file (./ipython_log.py).") +# +# # quick is harder to implement +flags['quick']=( + {'IPythonApp' : {'quick' : True}}, + "Enable quick startup with no config files." +) + +nosep_config = Config() +nosep_config.InteractiveShell.separate_in = '' +nosep_config.InteractiveShell.separate_out = '' +nosep_config.InteractiveShell.separate_out2 = '' + +flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.") + +flags['i'] = ( + {'IPythonApp' : {'force_interact' : True}}, + "If running code from the command line, become interactive afterwards." +) +flags['pylab'] = ( + {'IPythonApp' : {'pylab' : 'auto'}}, + """Pre-load matplotlib and numpy for interactive use with + the default matplotlib backend.""" +) + +aliases = dict(base_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', +)) #----------------------------------------------------------------------------- # Main classes and functions #----------------------------------------------------------------------------- -class IPythonApp(Application): +class IPythonApp(BaseIPythonApplication): name = u'ipython' - #: argparse formats better the 'usage' than the 'description' field - description = None - usage = usage.cl_usage - command_line_loader = IPAppConfigLoader + description = usage.cl_usage + # command_line_loader = IPAppConfigLoader default_config_file_name = default_config_file_name crash_handler_class = IPAppCrashHandler - - def create_default_config(self): - super(IPythonApp, self).create_default_config() - # Eliminate multiple lookups - Global = self.default_config.Global - - # Set all default values - Global.display_banner = True + flags = Dict(flags) + aliases = Dict(aliases) + classes = [TerminalInteractiveShell, ProfileDir, PlainTextFormatter] + # *do* autocreate requested profile + auto_create=Bool(True) + copy_config_files=Bool(True) + # configurables + ignore_old_config=Bool(False, config=True, + help="Suppress warning messages about legacy config files" + ) + quick = Bool(False, config=True, + help="""Start IPython quickly by skipping the loading of config files.""" + ) + def _quick_changed(self, name, old, new): + if new: + self.load_config_file = lambda *a, **kw: None + self.ignore_old_config=True + + gui = CaselessStrEnum(('qt','wx','gtk'), config=True, + help="Enable GUI event loop integration ('qt', 'wx', 'gtk')." + ) + pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'], + config=True, + help="""Pre-load matplotlib and numpy for interactive use, + selecting a particular matplotlib backend and loop integration. + """ + ) + 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. + force_interact = Bool(False, config=True, + help="""If a command or file is given via the command-line, + e.g. 'ipython foo.py""" + ) + 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 + interact=Bool(True) + + + def initialize(self, argv=None): + """Do actions after construct, but before starting the app.""" + super(IPythonApp, self).initialize(argv) + if not self.ignore_old_config: + check_for_old_config(self.ipython_dir) - # If the -c flag is given or a file is given to run at the cmd line - # like "ipython foo.py", normally we exit without starting the main - # loop. The force_interact config variable allows a user to override - # this and interact. It is also set by the -i cmd line flag, just - # like Python. - Global.force_interact = False - - # By default always interact by starting the IPython mainloop. - Global.interact = True - - # No GUI integration by default - Global.gui = False - # Pylab off by default - Global.pylab = False - - # Deprecated versions of gui support that used threading, we support - # them just for bacwards compatibility as an alternate spelling for - # '--gui X' - Global.qthread = False - Global.q4thread = False - Global.wthread = False - Global.gthread = False - - def load_file_config(self): - if hasattr(self.command_line_config.Global, 'quick'): - if self.command_line_config.Global.quick: - self.file_config = Config() - return - super(IPythonApp, self).load_file_config() - - def post_load_file_config(self): - if hasattr(self.command_line_config.Global, 'extra_extension'): - if not hasattr(self.file_config.Global, 'extensions'): - self.file_config.Global.extensions = [] - self.file_config.Global.extensions.append( - self.command_line_config.Global.extra_extension) - del self.command_line_config.Global.extra_extension - - def pre_construct(self): - config = self.master_config - - if hasattr(config.Global, 'classic'): - if config.Global.classic: - config.InteractiveShell.cache_size = 0 - config.PlainTextFormatter.pprint = False - config.InteractiveShell.prompt_in1 = '>>> ' - config.InteractiveShell.prompt_in2 = '... ' - config.InteractiveShell.prompt_out = '' - config.InteractiveShell.separate_in = \ - config.InteractiveShell.separate_out = \ - config.InteractiveShell.separate_out2 = '' - config.InteractiveShell.colors = 'NoColor' - config.InteractiveShell.xmode = 'Plain' - - if hasattr(config.Global, 'nosep'): - if config.Global.nosep: - config.InteractiveShell.separate_in = \ - config.InteractiveShell.separate_out = \ - config.InteractiveShell.separate_out2 = '' - - # if there is code of files to run from the cmd line, don't interact - # unless the -i flag (Global.force_interact) is true. - code_to_run = config.Global.get('code_to_run','') - file_to_run = False - if self.extra_args and self.extra_args[0]: - file_to_run = True - if file_to_run or code_to_run: - if not config.Global.force_interact: - config.Global.interact = False - - def construct(self): + # print self.extra_args + if self.extra_args: + self.file_to_run = self.extra_args[0] + # create the shell + self.init_shell() + # and draw the banner + self.init_banner() + # Now a variety of things that happen after the banner is printed. + self.init_gui_pylab() + self.init_extensions() + self.init_code() + + def init_shell(self): + """initialize the InteractiveShell instance""" # I am a little hesitant to put these into InteractiveShell itself. # But that might be the place for them sys.path.insert(0, '') # Create an InteractiveShell instance. - self.shell = TerminalInteractiveShell.instance(config=self.master_config) - - def post_construct(self): - """Do actions after construct, but before starting the app.""" - config = self.master_config - # shell.display_banner should always be False for the terminal # based app, because we call shell.show_banner() by hand below # so the banner shows *before* all extension loading stuff. - self.shell.display_banner = False - if config.Global.display_banner and \ - config.Global.interact: - self.shell.show_banner() + self.shell = TerminalInteractiveShell.instance(config=self.config, + display_banner=False, profile_dir=self.profile_dir, + ipython_dir=self.ipython_dir) + def init_banner(self): + """optionally display the banner""" + if self.display_banner and self.interact: + self.shell.show_banner() # Make sure there is a space below the banner. if self.log_level <= logging.INFO: print - # Now a variety of things that happen after the banner is printed. - self._enable_gui_pylab() - self._load_extensions() - self._run_exec_lines() - self._run_exec_files() - self._run_cmd_line_code() - def _enable_gui_pylab(self): + def init_gui_pylab(self): """Enable GUI event loop integration, taking pylab into account.""" - Global = self.master_config.Global - - # Select which gui to use - if Global.gui: - gui = Global.gui - # The following are deprecated, but there's likely to be a lot of use - # of this form out there, so we might as well support it for now. But - # the --gui option above takes precedence. - elif Global.wthread: - gui = inputhook.GUI_WX - elif Global.qthread: - gui = inputhook.GUI_QT - elif Global.gthread: - gui = inputhook.GUI_GTK - else: - gui = None + gui = self.gui - # Using --pylab will also require gui activation, though which toolkit + # Using `pylab` will also require gui activation, though which toolkit # to use may be chosen automatically based on mpl configuration. - if Global.pylab: + if self.pylab: activate = self.shell.enable_pylab - if Global.pylab == 'auto': + if self.pylab == 'auto': gui = None else: - gui = Global.pylab + gui = self.pylab else: # Enable only GUI integration, no pylab activate = inputhook.enable_gui - if gui or Global.pylab: + if gui or self.pylab: try: self.log.info("Enabling GUI event loop integration, " - "toolkit=%s, pylab=%s" % (gui, Global.pylab) ) + "toolkit=%s, pylab=%s" % (gui, self.pylab) ) activate(gui) except: self.log.warn("Error in enabling GUI event loop integration:") self.shell.showtraceback() - def _load_extensions(self): - """Load all IPython extensions in Global.extensions. + 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.master_config.Global.extensions``. + the extensions listed in ``self.extensions``. """ + if not self.extensions: + return try: - if hasattr(self.master_config.Global, 'extensions'): - self.log.debug("Loading IPython extensions...") - extensions = self.master_config.Global.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() + 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 Global.exec_lines in the user's namespace.""" + """Run lines of code in IPythonApp.exec_lines in the user's namespace.""" + if not self.exec_lines: + return try: - if hasattr(self.master_config.Global, 'exec_lines'): - self.log.debug("Running code from Global.exec_lines...") - exec_lines = self.master_config.Global.exec_lines - for line in 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() + 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 Global.exec_lines:") + self.log.warn("Unknown error in handling IPythonApp.exec_lines:") self.shell.showtraceback() def _exec_file(self, fname): @@ -598,35 +467,36 @@ class IPythonApp(Application): 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: - if hasattr(self.master_config.Global, 'exec_files'): - self.log.debug("Running files in Global.exec_files...") - exec_files = self.master_config.Global.exec_files - for fname in exec_files: - self._exec_file(fname) + for fname in self.exec_files: + self._exec_file(fname) except: - self.log.warn("Unknown error in handling Global.exec_files:") + self.log.warn("Unknown error in handling IPythonApp.exec_files:") self.shell.showtraceback() def _run_cmd_line_code(self): - if hasattr(self.master_config.Global, 'code_to_run'): - line = self.master_config.Global.code_to_run + """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" % + 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() - return + # Like Python itself, ignore the second if the first of these is present - try: - fname = self.extra_args[0] - except: - pass - else: + elif self.file_to_run: + fname = self.file_to_run try: self._exec_file(fname) except: @@ -634,14 +504,14 @@ class IPythonApp(Application): fname) self.shell.showtraceback() - def start_app(self): - if not getattr(self.master_config.Global, 'ignore_old_config', False): - check_for_old_config(self.ipython_dir) - if self.master_config.Global.interact: + + def start(self): + # perform any prexec steps: + if self.interact: self.log.debug("Starting IPython's mainloop...") self.shell.mainloop() else: - self.log.debug("IPython not interactive, start_app is no-op...") + self.log.debug("IPython not interactive...") def load_default_config(ipython_dir=None): @@ -651,7 +521,8 @@ def load_default_config(ipython_dir=None): """ if ipython_dir is None: ipython_dir = get_ipython_dir() - cl = PyFileConfigLoader(default_config_file_name, ipython_dir) + profile_dir = os.path.join(ipython_dir, 'profile_default') + cl = PyFileConfigLoader(default_config_file_name, profile_dir) config = cl.load_config() return config @@ -659,6 +530,9 @@ def load_default_config(ipython_dir=None): def launch_new_instance(): """Create and run a full blown IPython instance""" app = IPythonApp() + app.initialize() + # print app.config + # print app.profile_dir.location app.start() diff --git a/IPython/lib/irunner.py b/IPython/lib/irunner.py index c132f58..ac652e5 100755 --- a/IPython/lib/irunner.py +++ b/IPython/lib/irunner.py @@ -304,9 +304,7 @@ class IPythonRunner(InteractiveRunner): def __init__(self,program = 'ipython',args=None,out=sys.stdout,echo=True): """New runner, optionally passing the ipython command to use.""" - args0 = ['--colors','NoColor', - '-pi1','In [\\#]: ', - '-pi2',' .\\D.: ', + args0 = ['colors=NoColor', '--no-term-title', '--no-autoindent'] if args is None: args = args0 diff --git a/IPython/testing/tools.py b/IPython/testing/tools.py index c829c8e..52130ee 100644 --- a/IPython/testing/tools.py +++ b/IPython/testing/tools.py @@ -158,8 +158,8 @@ def default_argv(): return ['--quick', # so no config file is loaded # Other defaults to minimize side effects on stdout - '--colors=NoColor', '--no-term-title','--no-banner', - '--autocall=0'] + 'colors=NoColor', '--no-term-title','--no-banner', + 'autocall=0'] def default_config(): @@ -197,7 +197,7 @@ def ipexec(fname, options=None): # For these subprocess calls, eliminate all prompt printing so we only see # output from script execution - prompt_opts = ['--prompt-in1=""', '--prompt-in2=""', '--prompt-out=""'] + prompt_opts = ['pi1=""', 'pi2=""', 'po=""'] cmdargs = ' '.join(default_argv() + prompt_opts + options) _ip = get_ipython()