diff --git a/IPython/config/loader.py b/IPython/config/loader.py index c2a5a86..c77b1b8 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -189,12 +189,15 @@ class ArgParseConfigLoader(CommandLineConfigLoader): class IPythonArgParseConfigLoader(ArgParseConfigLoader): def _add_other_arguments(self): - self.parser.add_argument('--ipythondir',dest='IPYTHONDIR',type=str, - help='set to override default location of IPYTHONDIR', + self.parser.add_argument('-ipythondir',dest='IPYTHONDIR',type=str, + help='Set to override default location of IPYTHONDIR.', default=NoDefault) - self.parser.add_argument('-p','--p',dest='PROFILE_NAME',type=str, - help='the string name of the ipython profile to be used', - default=None) - self.parser.add_argument('--debug',dest="DEBUG",action='store_true', - help='debug the application startup process', + self.parser.add_argument('-p','-profile',dest='PROFILE',type=str, + help='The string name of the ipython profile to be used.', + default=NoDefault) + self.parser.add_argument('-debug',dest="DEBUG",action='store_true', + help='Debug the application startup process.', + default=NoDefault) + self.parser.add_argument('-config_file',dest='CONFIG_FILE',type=str, + help='Set the config file name to override default.', default=NoDefault) diff --git a/IPython/core/application.py b/IPython/core/application.py index 82cc86c..5c528ff 100644 --- a/IPython/core/application.py +++ b/IPython/core/application.py @@ -59,7 +59,7 @@ class Application(object): """Start the application.""" self.attempt(self.create_default_config) self.attempt(self.pre_load_command_line_config) - self.attempt(self.load_command_line_config, action='exit') + self.attempt(self.load_command_line_config, action='abort') self.attempt(self.post_load_command_line_config) self.attempt(self.find_ipythondir) self.attempt(self.find_config_file_name) @@ -137,11 +137,18 @@ class Application(object): loader where they are resolved to an absolute path. """ - if self.command_line_config.PROFILE_NAME is not None: - self.profile_name = self.command_line_config.PROFILE_NAME + try: + self.config_file_name = self.command_line_config.CONFIG_FILE + except AttributeError: + pass + + try: + self.profile_name = self.command_line_config.PROFILE name_parts = self.config_file_name.split('.') name_parts.insert(1, '_' + self.profile_name + '.') self.config_file_name = ''.join(name_parts) + except AttributeError: + pass def find_config_file_paths(self): """Set the search paths for resolving the config file.""" @@ -168,7 +175,8 @@ class Application(object): self.config_file_name) self.file_config = Struct() else: - self.log("Config file loaded: %s" % loader.full_filename) + self.log("Config file loaded: %s" % loader.full_filename, + self.file_config) def post_load_file_config(self): """Do actions after the config file is loaded.""" @@ -178,8 +186,8 @@ class Application(object): """Merge the default, command line and file config objects.""" config = Struct() config.update(self.default_config) - config.update(self.command_line_config) config.update(self.file_config) + config.update(self.command_line_config) self.master_config = config self.log("Master config created:", self.master_config) diff --git a/IPython/core/ipapp.py b/IPython/core/ipapp.py index f52a55f..bd464f2 100644 --- a/IPython/core/ipapp.py +++ b/IPython/core/ipapp.py @@ -23,10 +23,22 @@ Notes # Imports #----------------------------------------------------------------------------- +import os +import sys +import warnings + from IPython.core.application import Application from IPython.core import release from IPython.core.iplib import InteractiveShell -from IPython.config.loader import IPythonArgParseConfigLoader +from IPython.config.loader import IPythonArgParseConfigLoader, NoDefault + +from IPython.utils.ipstruct import Struct + + +#----------------------------------------------------------------------------- +# Utilities and helpers +#----------------------------------------------------------------------------- + ipython_desc = """ A Python shell with automatic history (input and output), dynamic object @@ -34,10 +46,184 @@ introspection, easier configuration, command completion, access to the system shell and more. """ +def threaded_shell_warning(): + msg = """ + +The IPython threaded shells and their associated command line +arguments (pylab/wthread/gthread/qthread/q4thread) have been +deprecated. See the %gui magic for information on the new interface. +""" + warnings.warn(msg, category=DeprecationWarning, stacklevel=1) + + +#----------------------------------------------------------------------------- +# Main classes and functions +#----------------------------------------------------------------------------- + +cl_args = ( + (('-autocall',), dict( + type=int, dest='AUTOCALL', default=NoDefault, + help='Set the autocall value (0,1,2).') + ), + (('-autoindent',), dict( + action='store_true', dest='AUTOINDENT', default=NoDefault, + help='Turn on autoindenting.') + ), + (('-noautoindent',), dict( + action='store_false', dest='AUTOINDENT', default=NoDefault, + help='Turn off autoindenting.') + ), + (('-automagic',), dict( + action='store_true', dest='AUTOMAGIC', default=NoDefault, + help='Turn on the auto calling of magic commands.') + ), + (('-noautomagic',), dict( + action='store_false', dest='AUTOMAGIC', default=NoDefault, + help='Turn off the auto calling of magic commands.') + ), + (('-autoedit_syntax',), dict( + action='store_true', dest='AUTOEDIT_SYNTAX', default=NoDefault, + help='Turn on auto editing of files with syntax errors.') + ), + (('-noautoedit_syntax',), dict( + action='store_false', dest='AUTOEDIT_SYNTAX', default=NoDefault, + help='Turn off auto editing of files with syntax errors.') + ), + (('-banner',), dict( + action='store_true', dest='DISPLAY_BANNER', default=NoDefault, + help='Display a banner upon starting IPython.') + ), + (('-nobanner',), dict( + action='store_false', dest='DISPLAY_BANNER', default=NoDefault, + help="Don't display a banner upon starting IPython.") + ), + (('-c',), dict( + type=str, dest='C', default=NoDefault, + help="Execute the given command string.") + ), + (('-cache_size',), dict( + type=int, dest='CACHE_SIZE', default=NoDefault, + help="Set the size of the output cache.") + ), + (('-classic',), dict( + action='store_true', dest='CLASSIC', default=NoDefault, + help="Gives IPython a similar feel to the classic Python prompt.") + ), + (('-colors',), dict( + type=str, dest='COLORS', default=NoDefault, + help="Set the color scheme (NoColor, Linux, and LightBG).") + ), + (('-color_info',), dict( + action='store_true', dest='COLOR_INFO', default=NoDefault, + help="Enable using colors for info related things.") + ), + (('-nocolor_info',), dict( + action='store_false', dest='COLOR_INFO', default=NoDefault, + help="Disable using colors for info related things.") + ), + (('-confirm_exit',), dict( + action='store_true', dest='CONFIRM_EXIT', default=NoDefault, + help="Prompt the user when existing.") + ), + (('-noconfirm_exit',), dict( + action='store_false', dest='CONFIRM_EXIT', default=NoDefault, + help="Don't prompt the user when existing.") + ), + (('-deep_reload',), dict( + action='store_true', dest='DEEP_RELOAD', default=NoDefault, + help="Enable deep (recursive) reloading by default.") + ), + (('-nodeep_reload',), dict( + action='store_false', dest='DEEP_RELOAD', default=NoDefault, + help="Disable deep (recursive) reloading by default.") + ), + (('-editor',), dict( + type=str, dest='EDITOR', default=NoDefault, + help="Set the editor used by IPython (default to $EDITOR/vi/notepad).") + ), + (('-log','-l'), dict( + action='store_true', dest='LOGSTART', default=NoDefault, + help="Start logging to the default file (./ipython_log.py).") + ), + (('-logfile','-lf'), dict( + type=str, dest='LOGFILE', default=NoDefault, + help="Specify the name of your logfile.") + ), + (('-logplay','-lp'), dict( + type=str, dest='LOGPLAY', default=NoDefault, + help="Re-play a log file and then append to it.") + ), + (('-pdb',), dict( + action='store_true', dest='PDB', default=NoDefault, + help="Enable auto calling the pdb debugger after every exception.") + ), + (('-nopdb',), dict( + action='store_false', dest='PDB', default=NoDefault, + help="Disable auto calling the pdb debugger after every exception.") + ), + (('-pprint',), dict( + action='store_true', dest='PPRINT', default=NoDefault, + help="Enable auto pretty printing of results.") + ), + (('-nopprint',), dict( + action='store_false', dest='PPRINT', default=NoDefault, + help="Disable auto auto pretty printing of results.") + ), + (('-prompt_in1','-pi1'), dict( + type=str, dest='PROMPT_IN1', default=NoDefault, + help="Set the main input prompt ('In [\#]: ')") + ), + (('-prompt_in2','-pi2'), dict( + type=str, dest='PROMPT_IN2', default=NoDefault, + help="Set the secondary input prompt (' .\D.: ')") + ), + (('-prompt_out','-po'), dict( + type=str, dest='PROMPT_OUT', default=NoDefault, + help="Set the output prompt ('Out[\#]:')") + ), + (('-quick',), dict( + action='store_true', dest='QUICK', default=NoDefault, + help="Enable quick startup with no config files.") + ), + (('-readline',), dict( + action='store_true', dest='READLINE_USE', default=NoDefault, + help="Enable readline for command line usage.") + ), + (('-noreadline',), dict( + action='store_false', dest='READLINE_USE', default=NoDefault, + help="Disable readline for command line usage.") + ), + (('-screen_length','-sl'), dict( + type=int, dest='SCREEN_LENGTH', default=NoDefault, + help='Number of lines on screen, used to control printing of long strings.') + ), + (('-separate_in','-si'), dict( + type=str, dest='SEPARATE_IN', default=NoDefault, + help="Separator before input prompts. Default '\n'.") + ), + (('-separate_out','-so'), dict( + type=str, dest='SEPARATE_OUT', default=NoDefault, + help="Separator before output prompts. Default 0 (nothing).") + ), + (('-separate_out2','-so2'), dict( + type=str, dest='SEPARATE_OUT2', default=NoDefault, + help="Separator after output prompts. Default 0 (nonight).") + ), + (('-nosep',), dict( + action='store_true', dest='NOSEP', default=NoDefault, + help="Eliminate all spacing between prompts.") + ), + (('-xmode',), dict( + type=str, dest='XMODE', default=NoDefault, + help="Exception mode ('Plain','Context','Verbose')") + ), +) + + class IPythonAppCLConfigLoader(IPythonArgParseConfigLoader): - arguments = ( - () - ) + + arguments = cl_args + class IPythonApp(Application): name = 'ipython' @@ -49,7 +235,72 @@ class IPythonApp(Application): description=ipython_desc, version=release.version) + def post_load_command_line_config(self): + """Do actions after loading cl config.""" + clc = self.command_line_config + + # This needs to be set here, the rest are set in pre_construct. + if hasattr(clc, 'CLASSIC'): + if clc.CLASSIC: clc.QUICK = 1 + + # Display the deprecation warnings about threaded shells + # if opts_all.pylab == 1: threaded_shell_warning() + # if opts_all.wthread == 1: threaded_shell_warning() + # if opts_all.qthread == 1: threaded_shell_warning() + # if opts_all.q4thread == 1: threaded_shell_warning() + # if opts_all.gthread == 1: threaded_shell_warning() + + def load_file_config(self): + if hasattr(self.command_line_config, 'QUICK'): + if self.command_line_config.QUICK: + self.file_config = Struct() + return + super(IPythonApp, self).load_file_config() + + def post_load_file_config(self): + """Logic goes here.""" + + def pre_construct(self): + config = self.master_config + + if hasattr(config, 'CLASSIC'): + if config.CLASSIC: + config.QUICK = 1 + config.CACHE_SIZE = 0 + config.PPRINT = 0 + config.PROMPT_IN1 = '>>> ' + config.PROMPT_IN2 = '... ' + config.PROMPT_OUT = '' + config.SEPARATE_IN = config.SEPARATE_OUT = config.SEPARATE_OUT2 = '' + config.COLORS = 'NoColor' + config.XMODE = 'Plain' + + # All this should be moved to traitlet handlers in InteractiveShell + if hasattr(config, 'NOSEP'): + if config.NOSEP: + config.SEPARATE_IN = config.SEPARATE_OUT = config.SEPARATE_OUT2 = '0' + + if hasattr(config, 'SEPARATE_IN'): + if config.SEPARATE_IN == '0': config.SEPARATE_IN = '' + config.SEPARATE_IN = config.SEPARATE_IN.replace('\\n','\n') + + if hasattr(config, 'SEPARATE_OUT'): + if config.SEPARATE_OUT == '0': config.SEPARATE_OUT = '' + config.SEPARATE_OUT = config.SEPARATE_OUT.replace('\\n','\n') + + if hasattr(config, 'SEPARATE_OUT'): + if config.SEPARATE_OUT2 == '0': config.SEPARATE_OUT2 = '' + config.SEPARATE_OUT2 = config.SEPARATE_OUT2.replace('\\n','\n') + def construct(self): + # I am a little hesitant to put these into InteractiveShell itself. + # But that might be the place for them + sys.path.insert(0, '') + # add personal ipythondir to sys.path so that users can put things in + # there for customization + sys.path.append(os.path.abspath(self.ipythondir)) + + # Create an InteractiveShell instance self.shell = InteractiveShell( name='__IP', parent=None, diff --git a/IPython/core/iplib.py b/IPython/core/iplib.py index 2d45d3a..81455c5 100644 --- a/IPython/core/iplib.py +++ b/IPython/core/iplib.py @@ -44,7 +44,7 @@ from IPython.core.magic import Magic from IPython.core.prompts import CachedOutput from IPython.core.component import Component from IPython.core.oldusersetup import user_setup -from IPython.core.usage import interactive_usage, banner_parts +from IPython.core.usage import interactive_usage, default_banner from IPython.extensions import pickleshare from IPython.external.Itpl import ItplNS @@ -55,7 +55,7 @@ from IPython.utils.genutils import * from IPython.utils.strdispatch import StrDispatch from IPython.utils.traitlets import ( - Int, Float, Str, Bool + Int, Float, Str, CBool, CaselessStrEnum, Enum ) #----------------------------------------------------------------------------- @@ -160,6 +160,15 @@ class SyntaxTB(ultratb.ListTB): self.last_syntax_error = None return e +def get_default_editor(): + try: + ed = os.environ['EDITOR'] + except KeyError: + if os.name == 'posix': + ed = 'vi' # the only one guaranteed to be there! + else: + ed = 'notepad' # same in Windows! + return ed #----------------------------------------------------------------------------- # Main IPython class @@ -187,47 +196,47 @@ class InteractiveShell(Component, Magic): """An enhanced console for Python.""" alias = [] - autocall = Bool(True) - autoedit_syntax = Bool(False) - autoindent = Bool(False) - automagic = Bool(True) + autocall = Enum((0,1,2), config_key='AUTOCALL') + autoedit_syntax = CBool(False, config_key='AUTOEDIT_SYNTAX') + autoindent = CBool(True, config_key='AUTOINDENT') + automagic = CBool(True, config_key='AUTOMAGIC') autoexec = [] - display_banner = Bool(True) + display_banner = CBool(True, config_key='DISPLAY_BANNER') banner = Str('') - c = Str('') - cache_size = Int(1000) - classic = Bool(False) - color_info = Int(0) - colors = Str('LightBG') - confirm_exit = Bool(True) - debug = Bool(False) - deep_reload = Bool(False) - embedded = Bool(False) - editor = Str('0') + banner1 = Str(default_banner, config_key='BANNER1') + banner2 = Str('', config_key='BANNER2') + c = Str('', config_key='C') + cache_size = Int(1000, config_key='CACHE_SIZE') + classic = CBool(False, config_key='CLASSIC') + color_info = CBool(True, config_key='COLOR_INFO') + colors = CaselessStrEnum(('NoColor','LightBG','Linux'), + default_value='LightBG', config_key='COLORS') + confirm_exit = CBool(True, config_key='CONFIRM_EXIT') + debug = CBool(False) + deep_reload = CBool(False, config_key='DEEP_RELOAD') + embedded = CBool(False) + editor = Str(get_default_editor(), config_key='EDITOR') filename = Str("") - help = Bool(False) - interactive = Bool(False) - logstart = Bool(False, config_key='LOGSTART') - logfile = Str('') - logplay = Str('') - messages = Bool(True) - multi_line_specials = Bool(True) - nosep = Bool(False) + help = CBool(False) + interactive = CBool(False) + logstart = CBool(False, config_key='LOGSTART') + logfile = Str('', config_key='LOGFILE') + logplay = Str('', config_key='LOGPLAY') + multi_line_specials = CBool(True) object_info_string_level = Int(0) pager = Str('less') - pdb = Bool(False) - pprint = Bool(True) - profile = Str('') - prompt_in1 = Str('In [\\#]: ') - prompt_in2 = Str(' .\\D.: ') - prompt_out = Str('Out[\\#]: ') - prompts_pad_left = Bool(True) - pydb = Bool(False) - quick = Bool(False) - quiet = Bool(False) - - readline_use = Bool(True) - readline_merge_completions = Bool(True) + pdb = CBool(False, config_key='PDB') + pprint = CBool(True, config_key='PPRINT') + profile = Str('', config_key='PROFILE') + prompt_in1 = Str('In [\\#]: ', config_key='PROMPT_IN1') + prompt_in2 = Str(' .\\D.: ', config_key='PROMPT_IN2') + prompt_out = Str('Out[\\#]: ', config_key='PROMPT_OUT1') + prompts_pad_left = CBool(True) + pydb = CBool(False) + quiet = CBool(False) + + readline_use = CBool(True, config_key='READLINE_USE') + readline_merge_completions = CBool(True) readline_omit__names = Int(0) readline_remove_delims = '-/~' readline_parse_and_bind = [ @@ -248,30 +257,36 @@ class InteractiveShell(Component, Magic): '"\C-u": unix-line-discard', ] - screen_length = Int(0) - separate_in = Str('\n') - separate_out = Str('') - separate_out2 = Str('') + screen_length = Int(0, config_key='SCREEN_LENGTH') + separate_in = Str('\n', config_key='SEPARATE_IN') + separate_out = Str('', config_key='SEPARATE_OUT') + separate_out2 = Str('', config_key='SEPARATE_OUT2') system_header = Str('IPython system call: ') - system_verbose = Bool(False) - term_title = Bool(True) - wildcards_case_sensitive = Bool(True) - xmode = Str('Context') - magic_docstrings = Bool(False) + system_verbose = CBool(False) + term_title = CBool(True) + wildcards_case_sensitive = CBool(True) + xmode = CaselessStrEnum(('Context','Plain', 'Verbose'), + default_value='Context', config_key='XMODE') + magic_docstrings = CBool(False) # class attribute to indicate whether the class supports threads or not. # Subclasses with thread support should override this as needed. isthreaded = False def __init__(self, name, parent=None, config=None, usage=None, - user_ns=None, user_global_ns=None, banner2='', + user_ns=None, user_global_ns=None, + banner1='', banner2='', 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) self.init_instance_attrs() self.init_usage(usage) - self.init_banner(banner2) + self.init_banner(banner1, banner2) self.init_embedded(embedded) self.init_create_namespaces(user_ns, user_global_ns) self.init_history() @@ -292,9 +307,45 @@ class InteractiveShell(Component, Magic): self.init_logger() self.init_aliases() self.init_builtins() + + # pre_config_initialization self.init_shadow_hist() + + # The next section should contain averything that was in ipmaker. self.init_logstart() - self.post_config_initialization() + + # The following was in post_config_initialization + self.init_inspector() + self.init_readline() + self.init_prompts() + self.init_displayhook() + self.init_reload_doctest() + self.init_magics() + self.init_pdb() + self.hooks.late_startup_hook() + self.init_exec_commands() + + #------------------------------------------------------------------------- + # Traitlet changed handlers + #------------------------------------------------------------------------- + + def _banner1_changed(self): + self.compute_banner() + + def _banner2_changed(self): + self.compute_banner() + + @property + def usable_screen_length(self): + if self.screen_length == 0: + return 0 + else: + num_lines_bot = self.separate_in.count('\n')+1 + return self.screen_length - num_lines_bot + + #------------------------------------------------------------------------- + # init_* methods called by __init__ + #------------------------------------------------------------------------- def init_instance_attrs(self): self.jobs = BackgroundJobManager() @@ -341,15 +392,21 @@ class InteractiveShell(Component, Magic): else: self.usage = usage - def init_banner(self, banner2): + def init_banner(self, banner1, banner2): if self.c: # regular python doesn't print the banner with -c self.display_banner = False - bp = banner_parts + if banner1: + self.banner1 = banner1 + if banner2: + self.banner2 = banner2 + self.compute_banner() + + def compute_banner(self): + self.banner = self.banner1 + '\n' if self.profile: - bp.append('IPython profile: %s\n' % self.profile) - if banner2 is not None: - bp.append(banner2) - self.banner = '\n'.join(bp) + self.banner += '\nIPython profile: %s\n' % self.profile + if self.banner2: + self.banner += '\n' + self.banner2 + '\n' def init_embedded(self, embedded): # We need to know whether the instance is meant for embedding, since @@ -512,6 +569,10 @@ class InteractiveShell(Component, Magic): histfname = 'history' self.histfile = os.path.join(self.config.IPYTHONDIR, histfname) + # Fill the history zero entry, user counter starts at 1 + self.input_hist.append('\n') + self.input_hist_raw.append('\n') + def init_encoding(self): # Get system encoding at startup time. Certain terminals (like Emacs # under Win32 have it set to None, and we need to have a known valid @@ -613,9 +674,9 @@ class InteractiveShell(Component, Magic): def init_logstart(self): if self.logplay: - IP.magic_logstart(self.logplay + ' append') + self.magic_logstart(self.logplay + ' append') elif self.logfile: - IP.magic_logstart(self.logfile) + self.magic_logstart(self.logfile) elif self.logstart: self.magic_logstart() @@ -687,7 +748,8 @@ class InteractiveShell(Component, Magic): # This method will add the necessary builtins for operation, but # tracking what it did via the builtins_added dict. - #TODO: remove this, redundant + #TODO: remove this, redundant. I don't understand why this is + # redundant? self.add_builtins() def init_shadow_hist(self): @@ -701,24 +763,100 @@ class InteractiveShell(Component, Magic): sys.exit() self.shadowhist = ipcorehist.ShadowHist(self.db) - def post_config_initialization(self): - """Post configuration init method - - This is called after the configuration files have been processed to - 'finalize' the initialization.""" - + def init_inspector(self): # Object inspector self.inspector = oinspect.Inspector(oinspect.InspectColors, PyColorize.ANSICodeColors, 'NoColor', self.object_info_string_level) - + + def init_readline(self): + """Command history completion/saving/reloading.""" + self.rl_next_input = None self.rl_do_indent = False - # Load readline proper - if self.readline_use: - self.init_readline() + if not self.readline_use: + return + + import IPython.utils.rlineimpl as readline + + if not readline.have_readline: + self.has_readline = 0 + self.readline = None + # no point in bugging windows users with this every time: + warn('Readline services not available on this platform.') + else: + sys.modules['readline'] = readline + import atexit + from IPython.core.completer import IPCompleter + self.Completer = IPCompleter(self, + self.user_ns, + self.user_global_ns, + self.readline_omit__names, + self.alias_table) + sdisp = self.strdispatchers.get('complete_command', StrDispatch()) + self.strdispatchers['complete_command'] = sdisp + self.Completer.custom_completers = sdisp + # Platform-specific configuration + if os.name == 'nt': + self.readline_startup_hook = readline.set_pre_input_hook + else: + self.readline_startup_hook = readline.set_startup_hook + + # Load user's initrc file (readline config) + # Or if libedit is used, load editrc. + inputrc_name = os.environ.get('INPUTRC') + if inputrc_name is None: + home_dir = get_home_dir() + if home_dir is not None: + inputrc_name = '.inputrc' + if readline.uses_libedit: + inputrc_name = '.editrc' + inputrc_name = os.path.join(home_dir, inputrc_name) + if os.path.isfile(inputrc_name): + try: + readline.read_init_file(inputrc_name) + except: + warn('Problems reading readline initialization file <%s>' + % inputrc_name) + + self.has_readline = 1 + self.readline = readline + # save this in sys so embedded copies can restore it properly + sys.ipcompleter = self.Completer.complete + self.set_completer() + + # Configure readline according to user's prefs + # This is only done if GNU readline is being used. If libedit + # is being used (as on Leopard) the readline config is + # not run as the syntax for libedit is different. + if not readline.uses_libedit: + for rlcommand in self.readline_parse_and_bind: + #print "loading rl:",rlcommand # dbg + readline.parse_and_bind(rlcommand) + + # Remove some chars from the delimiters list. If we encounter + # unicode chars, discard them. + delims = readline.get_completer_delims().encode("ascii", "ignore") + delims = delims.translate(string._idmap, + self.readline_remove_delims) + readline.set_completer_delims(delims) + # otherwise we end up with a monster history after a while: + readline.set_history_length(1000) + try: + #print '*** Reading readline history' # dbg + readline.read_history_file(self.histfile) + except IOError: + pass # It doesn't exist yet. + + atexit.register(self.atexit_operations) + del atexit + + # Configure auto-indent for all platforms + self.set_autoindent(self.autoindent) + + def init_prompts(self): # Initialize cache, set in/out prompts and printing system self.outputcache = CachedOutput(self, self.cache_size, @@ -737,6 +875,7 @@ class InteractiveShell(Component, Magic): except AttributeError: pass + def init_displayhook(self): # I don't like assigning globally to sys, because it means when # embedding instances, each embedded instance overrides the previous # choice. But sys.displayhook seems to be called internally by exec, @@ -745,24 +884,25 @@ class InteractiveShell(Component, Magic): self.sys_displayhook = sys.displayhook sys.displayhook = self.outputcache + def init_reload_doctest(self): # Do a proper resetting of doctest, including the necessary displayhook # monkeypatching try: doctest_reload() except ImportError: warn("doctest module does not exist.") - + + def init_magics(self): # Set user colors (don't do it in the constructor above so that it # doesn't crash if colors option is invalid) self.magic_colors(self.colors) + def init_pdb(self): # Set calling of pdb on exceptions + # self.call_pdb is a property self.call_pdb = self.pdb - - - self.hooks.late_startup_hook() - + def init_exec_commands(self): for cmd in self.autoexec: #print "autoexec>",cmd #dbg self.api.runlines(cmd) @@ -809,9 +949,12 @@ class InteractiveShell(Component, Magic): self.user_ns['_sh'] = shadowns - # Fill the history zero entry, user counter starts at 1 - self.input_hist.append('\n') - self.input_hist_raw.append('\n') + # Put 'help' in the user namespace + try: + from site import _Helper + self.user_ns['help'] = _Helper() + except ImportError: + warn('help() not available - check site.py') def add_builtins(self): """Store ipython references into the builtin namespace. @@ -825,6 +968,17 @@ class InteractiveShell(Component, Magic): # when it is refactored. __builtin__.exit = Quitter(self,'exit') __builtin__.quit = Quitter(self,'quit') + + # Recursive reload + try: + from IPython.lib import deepreload + if self.deep_reload: + __builtin__.reload = deepreload.reload + else: + __builtin__.dreload = deepreload.reload + del deepreload + except ImportError: + pass # TODO: deprecate all of these, they are unsafe. Why though? builtins_new = dict(__IPYTHON__ = self, @@ -1287,87 +1441,6 @@ class InteractiveShell(Component, Magic): self.readline.insert_text(self.rl_next_input) self.rl_next_input = None - def init_readline(self): - """Command history completion/saving/reloading.""" - - - import IPython.utils.rlineimpl as readline - - if not readline.have_readline: - self.has_readline = 0 - self.readline = None - # no point in bugging windows users with this every time: - warn('Readline services not available on this platform.') - else: - sys.modules['readline'] = readline - import atexit - from IPython.core.completer import IPCompleter - self.Completer = IPCompleter(self, - self.user_ns, - self.user_global_ns, - self.readline_omit__names, - self.alias_table) - sdisp = self.strdispatchers.get('complete_command', StrDispatch()) - self.strdispatchers['complete_command'] = sdisp - self.Completer.custom_completers = sdisp - # Platform-specific configuration - if os.name == 'nt': - self.readline_startup_hook = readline.set_pre_input_hook - else: - self.readline_startup_hook = readline.set_startup_hook - - # Load user's initrc file (readline config) - # Or if libedit is used, load editrc. - inputrc_name = os.environ.get('INPUTRC') - if inputrc_name is None: - home_dir = get_home_dir() - if home_dir is not None: - inputrc_name = '.inputrc' - if readline.uses_libedit: - inputrc_name = '.editrc' - inputrc_name = os.path.join(home_dir, inputrc_name) - if os.path.isfile(inputrc_name): - try: - readline.read_init_file(inputrc_name) - except: - warn('Problems reading readline initialization file <%s>' - % inputrc_name) - - self.has_readline = 1 - self.readline = readline - # save this in sys so embedded copies can restore it properly - sys.ipcompleter = self.Completer.complete - self.set_completer() - - # Configure readline according to user's prefs - # This is only done if GNU readline is being used. If libedit - # is being used (as on Leopard) the readline config is - # not run as the syntax for libedit is different. - if not readline.uses_libedit: - for rlcommand in self.readline_parse_and_bind: - #print "loading rl:",rlcommand # dbg - readline.parse_and_bind(rlcommand) - - # Remove some chars from the delimiters list. If we encounter - # unicode chars, discard them. - delims = readline.get_completer_delims().encode("ascii", "ignore") - delims = delims.translate(string._idmap, - self.readline_remove_delims) - readline.set_completer_delims(delims) - # otherwise we end up with a monster history after a while: - readline.set_history_length(1000) - try: - #print '*** Reading readline history' # dbg - readline.read_history_file(self.histfile) - except IOError: - pass # It doesn't exist yet. - - atexit.register(self.atexit_operations) - del atexit - - # Configure auto-indent for all platforms - self.set_autoindent(self.autoindent) - def ask_yes_no(self,prompt,default=True): if self.quiet: return True @@ -2480,7 +2553,7 @@ class InteractiveShell(Component, Magic): #print 'line:<%r>' % line # dbg self.magic_pinfo(line) else: - page(self.usage,screen_lines=self.screen_length) + page(self.usage,screen_lines=self.usable_screen_length) return '' # Empty string is needed here! except: # Pass any other exceptions through to the normal handler @@ -2562,7 +2635,6 @@ class InteractiveShell(Component, Magic): """Handle interactive exit. This method calls the ask_exit callback.""" - print "IN self.exit", self.confirm_exit if self.confirm_exit: if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'): self.ask_exit() diff --git a/IPython/core/magic.py b/IPython/core/magic.py index a1930c2..e46dcff 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -485,7 +485,7 @@ Currently the magic system has the following functions:\n""" (' '+mesc).join(self.lsmagic()), Magic.auto_status[self.shell.automagic] ) ) - page(outmsg,screen_lines=self.shell.screen_length) + page(outmsg,screen_lines=self.shell.usable_screen_length) def magic_autoindent(self, parameter_s = ''): @@ -1423,7 +1423,7 @@ Currently the magic system has the following functions:\n""" output = stdout_trap.getvalue() output = output.rstrip() - page(output,screen_lines=self.shell.screen_length) + page(output,screen_lines=self.shell.usable_screen_length) print sys_exit, dump_file = opts.D[0] @@ -2530,10 +2530,10 @@ Defaulting color scheme to 'NoColor'""" than more) in your system, using colored object information displays will not work properly. Test it and see.""" - self.shell.color_info = 1 - self.shell.color_info + self.shell.color_info = not self.shell.color_info self.magic_colors(self.shell.colors) print 'Object introspection functions have now coloring:', - print ['OFF','ON'][self.shell.color_info] + print ['OFF','ON'][int(self.shell.color_info)] def magic_Pprint(self, parameter_s=''): """Toggle pretty printing on/off.""" @@ -3267,7 +3267,7 @@ Defaulting color scheme to 'NoColor'""" return page(self.shell.pycolorize(cont), - screen_lines=self.shell.screen_length) + screen_lines=self.shell.usable_screen_length) def _rerun_pasted(self): """ Rerun a previously pasted command. diff --git a/IPython/core/usage.py b/IPython/core/usage.py index a931b0b..62eb175 100644 --- a/IPython/core/usage.py +++ b/IPython/core/usage.py @@ -578,9 +578,11 @@ quick_guide = """\ help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more.""" -banner_parts = [ +default_banner_parts = [ 'Python %s' % (sys.version.split('\n')[0],), 'Type "copyright", "credits" or "license" for more information.\n', 'IPython %s -- An enhanced Interactive Python.' % (release.version,), quick_guide ] + +default_banner = '\n'.join(default_banner_parts) diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index 0b25b76..23e0e96 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -858,4 +858,42 @@ class CBool(Bool): try: return bool(value) except: - self.error(obj, value) \ No newline at end of file + self.error(obj, value) + +class Enum(TraitletType): + + def __init__(self, values, default_value=None, allow_none=True, **metadata): + self.values = values + self._allow_none = allow_none + super(Enum, self).__init__(default_value, **metadata) + + def validate(self, obj, value): + if value is None: + if self._allow_none: + return value + + if value in self.values: + return value + self.error(obj, value) + + def info(self): + """ Returns a description of the trait.""" + result = 'any of ' + repr(self.values) + if self._allow_none: + return result + ' or None' + return result + +class CaselessStrEnum(Enum): + + def validate(self, obj, value): + if value is None: + if self._allow_none: + return value + + if not isinstance(value, str): + self.error(obj, value) + + for v in self.values: + if v.lower() == value.lower(): + return v + self.error(obj, value) \ No newline at end of file