From 737ad9d6403c3daa5f414cc1f42fb7096e9ac7b2 2009-08-19 06:17:35 From: Brian Granger Date: 2009-08-19 06:17:35 Subject: [PATCH] More work on InteractiveShell and ipmaker. It works! --- diff --git a/IPython/core/ipapp.py b/IPython/core/ipapp.py index bd464f2..a249447 100644 --- a/IPython/core/ipapp.py +++ b/IPython/core/ipapp.py @@ -213,10 +213,23 @@ cl_args = ( action='store_true', dest='NOSEP', default=NoDefault, help="Eliminate all spacing between prompts.") ), + (('-term_title',), dict( + action='store_true', dest='TERM_TITLE', default=NoDefault, + help="Enable auto setting the terminal title.") + ), + (('-noterm_title',), dict( + action='store_false', dest='TERM_TITLE', default=NoDefault, + help="Disable auto setting the terminal title.") + ), (('-xmode',), dict( type=str, dest='XMODE', default=NoDefault, help="Exception mode ('Plain','Context','Verbose')") ), + # These are only here to get the proper deprecation warnings + (('-pylab','-wthread','-qthread','-q4thread','-gthread'), dict( + action='store_true', dest='THREADED_SHELL', default=NoDefault, + help="These command line flags are deprecated, see the 'gui' magic.") + ), ) @@ -244,11 +257,9 @@ class IPythonApp(Application): 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() + if hasattr(clc, 'THREADED_SHELL'): + threaded_shell_warning() + del clc['THREADED_SHELL'] def load_file_config(self): if hasattr(self.command_line_config, 'QUICK'): @@ -276,22 +287,13 @@ class IPythonApp(Application): config.XMODE = 'Plain' # All this should be moved to traitlet handlers in InteractiveShell + # But, currently InteractiveShell doesn't have support for changing + # these values at runtime. Once we support that, this should + # be moved there!!! 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 diff --git a/IPython/core/iplib.py b/IPython/core/iplib.py index 81455c5..34c5742 100644 --- a/IPython/core/iplib.py +++ b/IPython/core/iplib.py @@ -53,9 +53,10 @@ from IPython.utils.ipstruct import Struct from IPython.utils import PyColorize from IPython.utils.genutils import * from IPython.utils.strdispatch import StrDispatch +from IPython.utils.platutils import toggle_set_term_title, set_term_title from IPython.utils.traitlets import ( - Int, Float, Str, CBool, CaselessStrEnum, Enum + Int, Float, Str, CBool, CaselessStrEnum, Enum, List ) #----------------------------------------------------------------------------- @@ -170,6 +171,19 @@ def get_default_editor(): ed = 'notepad' # same in Windows! return ed + +class SeparateStr(Str): + """A Str subclass to validate separate_in, separate_out, etc. + + This is a Str based traitlet that converts '0'->'' and '\\n'->'\n'. + """ + + def validate(self, obj, value): + if value == '0': value = '' + value = value.replace('\\n','\n') + return super(SeparateStr, self).validate(obj, value) + + #----------------------------------------------------------------------------- # Main IPython class #----------------------------------------------------------------------------- @@ -195,12 +209,10 @@ def get_default_editor(): class InteractiveShell(Component, Magic): """An enhanced console for Python.""" - alias = [] 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 = CBool(True, config_key='DISPLAY_BANNER') banner = Str('') banner1 = Str(default_banner, config_key='BANNER1') @@ -212,69 +224,76 @@ class InteractiveShell(Component, Magic): colors = CaselessStrEnum(('NoColor','LightBG','Linux'), default_value='LightBG', config_key='COLORS') confirm_exit = CBool(True, config_key='CONFIRM_EXIT') - debug = CBool(False) + debug = CBool(False, config_key='DEBUG') deep_reload = CBool(False, config_key='DEEP_RELOAD') embedded = CBool(False) editor = Str(get_default_editor(), config_key='EDITOR') filename = Str("") - help = CBool(False) - interactive = CBool(False) + interactive = CBool(False, config_key='INTERACTIVE') 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') + multi_line_specials = CBool(True, config_key='MULTI_LINE_SPECIALS') + object_info_string_level = Enum((0,1,2), default_value=0, + config_keys='OBJECT_INFO_STRING_LEVEL') + pager = Str('less', config_key='PAGER') 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) + prompts_pad_left = CBool(True, config_key='PROMPTS_PAD_LEFT') + quiet = CBool(False, config_key='QUIET') 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 = [ - 'tab: complete', - '"\C-l": possible-completions', - 'set show-all-if-ambiguous on', - '"\C-o": tab-insert', - '"\M-i": " "', - '"\M-o": "\d\d\d\d"', - '"\M-I": "\d\d\d\d"', - '"\C-r": reverse-search-history', - '"\C-s": forward-search-history', - '"\C-p": history-search-backward', - '"\C-n": history-search-forward', - '"\e[A": history-search-backward', - '"\e[B": history-search-forward', - '"\C-k": kill-line', - '"\C-u": unix-line-discard', - ] + readline_merge_completions = CBool(True, + config_key='READLINE_MERGE_COMPLETIONS') + readline_omit__names = Enum((0,1,2), default_value=0, + config_key='READLINE_OMIT_NAMES') + readline_remove_delims = Str('-/~', config_key='READLINE_REMOVE_DELIMS') + readline_parse_and_bind = List([ + 'tab: complete', + '"\C-l": possible-completions', + 'set show-all-if-ambiguous on', + '"\C-o": tab-insert', + '"\M-i": " "', + '"\M-o": "\d\d\d\d"', + '"\M-I": "\d\d\d\d"', + '"\C-r": reverse-search-history', + '"\C-s": forward-search-history', + '"\C-p": history-search-backward', + '"\C-n": history-search-forward', + '"\e[A": history-search-backward', + '"\e[B": history-search-forward', + '"\C-k": kill-line', + '"\C-u": unix-line-discard', + ], allow_none=False, config_key='READLINE_PARSE_AND_BIND' + ) 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 = CBool(False) - term_title = CBool(True) - wildcards_case_sensitive = CBool(True) + + # Use custom TraitletTypes that convert '0'->'' and '\\n'->'\n' + separate_in = SeparateStr('\n', config_key='SEPARATE_IN') + separate_out = SeparateStr('', config_key='SEPARATE_OUT') + separate_out2 = SeparateStr('', config_key='SEPARATE_OUT2') + + system_header = Str('IPython system call: ', config_key='SYSTEM_HEADER') + system_verbose = CBool(False, config_key='SYSTEM_VERBOSE') + term_title = CBool(False, config_key='TERM_TITLE') + wildcards_case_sensitive = CBool(True, config_key='WILDCARDS_CASE_SENSITIVE') xmode = CaselessStrEnum(('Context','Plain', 'Verbose'), default_value='Context', config_key='XMODE') - magic_docstrings = CBool(False) + + alias = List(allow_none=False, config_key='ALIAS') + autoexec = List(allow_none=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, + user_ns=None, user_global_ns=None, banner1='', banner2='', custom_exceptions=((),None), embedded=False): @@ -285,6 +304,7 @@ class InteractiveShell(Component, Magic): super(InteractiveShell, self).__init__(parent, config=config, name=name) self.init_instance_attrs() + self.init_term_title() self.init_usage(usage) self.init_banner(banner1, banner2) self.init_embedded(embedded) @@ -343,6 +363,9 @@ class InteractiveShell(Component, Magic): num_lines_bot = self.separate_in.count('\n')+1 return self.screen_length - num_lines_bot + def _term_title_changed(self, name, new_value): + self.init_term_title() + #------------------------------------------------------------------------- # init_* methods called by __init__ #------------------------------------------------------------------------- @@ -386,6 +409,14 @@ class InteractiveShell(Component, Magic): # Indentation management self.indent_current_nsp = 0 + def init_term_title(self): + # Enable or disable the terminal title. + if self.term_title: + toggle_set_term_title(True) + set_term_title('IPython: ' + abbrev_cwd()) + else: + toggle_set_term_title(False) + def init_usage(self, usage=None): if usage is None: self.usage = interactive_usage @@ -564,7 +595,7 @@ class InteractiveShell(Component, Magic): # Now the history file try: - histfname = 'history-%s' % self.config.PROFILE + histfname = 'history-%s' % self.profile except AttributeError: histfname = 'history' self.histfile = os.path.join(self.config.IPYTHONDIR, histfname) @@ -903,8 +934,8 @@ class InteractiveShell(Component, Magic): self.call_pdb = self.pdb def init_exec_commands(self): - for cmd in self.autoexec: - #print "autoexec>",cmd #dbg + for cmd in self.config.EXECUTE: + print "execute:", cmd self.api.runlines(cmd) batchrun = False diff --git a/IPython/core/magic.py b/IPython/core/magic.py index e46dcff..4500f4b 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -2856,8 +2856,7 @@ Defaulting color scheme to 'NoColor'""" try: os.chdir(os.path.expanduser(ps)) if self.shell.term_title: - #print 'set term title:',self.shell.term_title # dbg - platutils.set_term_title('IPy ' + abbrev_cwd()) + platutils.set_term_title('IPython: ' + abbrev_cwd()) except OSError: print sys.exc_info()[1] else: @@ -2870,7 +2869,7 @@ Defaulting color scheme to 'NoColor'""" else: os.chdir(self.shell.home_dir) if self.shell.term_title: - platutils.set_term_title("IPy ~") + platutils.set_term_title('IPython: ' + '~') cwd = os.getcwd() dhist = self.shell.user_ns['_dh'] diff --git a/IPython/utils/platutils.py b/IPython/utils/platutils.py index ab5c2a7..2c3e52a 100644 --- a/IPython/utils/platutils.py +++ b/IPython/utils/platutils.py @@ -54,7 +54,6 @@ def toggle_set_term_title(val): def set_term_title(title): """Set terminal title using the necessary platform-dependent calls.""" - if _platutils.ignore_termtitle: return _platutils.set_term_title(title) diff --git a/IPython/utils/platutils_posix.py b/IPython/utils/platutils_posix.py index 3c38dba..a618d15 100644 --- a/IPython/utils/platutils_posix.py +++ b/IPython/utils/platutils_posix.py @@ -17,17 +17,18 @@ import os ignore_termtitle = True + def _dummy_op(*a, **b): """ A no-op function """ def _set_term_title_xterm(title): """ Change virtual terminal title in xterm-workalikes """ - sys.stdout.write('\033]0;%s\007' % title) +TERM = os.environ.get('TERM','') -if os.environ.get('TERM','') == 'xterm': +if (TERM == 'xterm') or (TERM == 'xterm-color'): set_term_title = _set_term_title_xterm else: set_term_title = _dummy_op diff --git a/IPython/utils/platutils_win32.py b/IPython/utils/platutils_win32.py index 9afc060..68e5017 100644 --- a/IPython/utils/platutils_win32.py +++ b/IPython/utils/platutils_win32.py @@ -26,6 +26,7 @@ try: """Set terminal title using ctypes to access the Win32 APIs.""" SetConsoleTitleW(title) + except ImportError: def set_term_title(title): """Set terminal title using the 'title' command.""" diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index 23e0e96..216df41 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -52,10 +52,15 @@ Authors: import inspect import sys import types -from types import InstanceType, ClassType, FunctionType +from types import ( + InstanceType, ClassType, FunctionType, + ListType, TupleType +) ClassTypes = (ClassType, type) +SequenceTypes = (ListType, TupleType) + #----------------------------------------------------------------------------- # Basic classes #----------------------------------------------------------------------------- @@ -860,7 +865,9 @@ class CBool(Bool): except: self.error(obj, value) + class Enum(TraitletType): + """An enum that whose value must be in a given sequence.""" def __init__(self, values, default_value=None, allow_none=True, **metadata): self.values = values @@ -884,6 +891,7 @@ class Enum(TraitletType): return result class CaselessStrEnum(Enum): + """An enum of strings that are caseless in validate.""" def validate(self, obj, value): if value is None: @@ -896,4 +904,22 @@ class CaselessStrEnum(Enum): for v in self.values: if v.lower() == value.lower(): return v - self.error(obj, value) \ No newline at end of file + self.error(obj, value) + + +class List(Instance): + """An instance of a Python list.""" + + def __init__(self, default_value=None, allow_none=True, **metadata): + """Create a list traitlet type from a list or tuple. + + The default value is created by doing ``list(default_value)``, + which creates a copy of the ``default_value``. + """ + if default_value is None: + args = ((),) + elif isinstance(default_value, SequenceTypes): + args = (default_value,) + + super(List,self).__init__(klass=list, args=args, + allow_none=allow_none, **metadata)