From 63ad14995578bc184bf5a5b226e619a9d4f410ee 2011-10-29 04:07:50 From: MinRK Date: 2011-10-29 04:07:50 Subject: [PATCH] add %config magic for configuring IPython --- diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 27d65a4..0c2d662 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -379,6 +379,7 @@ class InteractiveShell(SingletonConfigurable, Magic): # This is where traits with a config_key argument are updated # from the values on config. super(InteractiveShell, self).__init__(config=config) + self.configurables = [self] # These are relatively independent and stateless self.init_ipython_dir(ipython_dir) @@ -602,9 +603,11 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_display_formatter(self): self.display_formatter = DisplayFormatter(config=self.config) + self.configurables.append(self.display_formatter) def init_display_pub(self): self.display_pub = self.display_pub_class(config=self.config) + self.configurables.append(self.display_pub) def init_displayhook(self): # Initialize displayhook, set in/out prompts and printing system @@ -620,6 +623,7 @@ class InteractiveShell(SingletonConfigurable, Magic): ps_out = self.prompt_out, pad_left = self.prompts_pad_left ) + self.configurables.append(self.displayhook) # This is a context manager that installs/revmoes the displayhook at # the appropriate time. self.display_trap = DisplayTrap(hook=self.displayhook) @@ -1435,6 +1439,7 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_history(self): """Sets up the command history, and starts regular autosaves.""" self.history_manager = HistoryManager(shell=self, config=self.config) + self.configurables.append(self.history_manager) #------------------------------------------------------------------------- # Things related to exception handling and tracebacks (not debugging) @@ -1856,6 +1861,7 @@ class InteractiveShell(SingletonConfigurable, Magic): use_readline=self.has_readline, config=self.config, ) + self.configurables.append(self.Completer) # Add custom completers to the basic ones built into IPCompleter sdisp = self.strdispatchers.get('complete_command', StrDispatch()) @@ -2112,6 +2118,7 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_alias(self): self.alias_manager = AliasManager(shell=self, config=self.config) + self.configurables.append(self.alias_manager) self.ns_table['alias'] = self.alias_manager.alias_table, #------------------------------------------------------------------------- @@ -2120,9 +2127,12 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_extension_manager(self): self.extension_manager = ExtensionManager(shell=self, config=self.config) + self.configurables.append(self.extension_manager) def init_plugin_manager(self): self.plugin_manager = PluginManager(config=self.config) + self.configurables.append(self.plugin_manager) + #------------------------------------------------------------------------- # Things related to payloads @@ -2130,6 +2140,7 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_payload(self): self.payload_manager = PayloadManager(config=self.config) + self.configurables.append(self.payload_manager) #------------------------------------------------------------------------- # Things related to the prefilter @@ -2137,6 +2148,7 @@ class InteractiveShell(SingletonConfigurable, Magic): def init_prefilter(self): self.prefilter_manager = PrefilterManager(shell=self, config=self.config) + self.configurables.append(self.prefilter_manager) # Ultimately this will be refactored in the new interpreter code, but # for now, we should expose the main prefilter method (there's legacy # code out there that may rely on this). diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 22a2375..7db0bd5 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -123,6 +123,8 @@ class Magic: auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.', 'Automagic is ON, % prefix NOT needed for magic functions.'] + + configurables = None #...................................................................... # some utility functions @@ -132,6 +134,8 @@ class Magic: if profile is None: self.magic_prun = self.profile_missing_notice self.shell = shell + if self.configurables is None: + self.configurables = [] # namespace for holding state we may need self._magic_state = Bunch() @@ -3607,4 +3611,92 @@ Defaulting color scheme to 'NoColor'""" with open(new_fname, 'w') as f: current.write(nb, f, new_format) + def magic_config(self, s): + """configure IPython + + %config Class.trait=value + or + %config Class + + This magic exposes most of the IPython config system. Any + Configurable class should be able to be configured with the simple + line: + + %config Class.trait=value + + Where `value` will be resolved in the user's namespace, if it is an + expression or variable name. + + Examples + -------- + + To see what classes are availabe for config, pass no arguments: + In [1]: %config + Available objects for config: + TerminalInteractiveShell + HistoryManager + PrefilterManager + AliasManager + IPCompleter + DisplayFormatter + DisplayPublisher + DisplayHook + ExtensionManager + PluginManager + PayloadManager + + # To view what is configurable on a given class, just pass the class name + In [2]: %config IPCompleter + IPCompleter options + ----------------- + IPCompleter.greedy= + Current: False + Activate greedy completion + This will enable completion on elements of lists, results of function calls, + etc., but can be unsafe because the code is actually evaluated on TAB. + + # but the real use is in setting values: + In [3]: %config IPCompleter.greedy = True + + # and these values are read from the user_ns if they are variables: + In [4]: feeling_greedy=False + + In [5]: %config IPCompleter.greedy = feeling_greedy + + """ + from IPython.config.loader import Config + classnames = [ c.__class__.__name__ for c in self.configurables ] + line = s.strip() + if not line: + # print available configurable names + print "Available objects for config:" + for name in classnames: + print " ", name + return + elif line in classnames: + # `%config TerminalInteractiveShell` will print trait info for + # TerminalInteractiveShell + c = self.configurables[classnames.index(line)] + cls = c.__class__ + help = cls.class_get_help(c) + # strip leading '--' from cl-args: + help = re.sub(r'^\-\-', '', help, flags=re.MULTILINE) + print help + return + elif '=' not in line: + raise UsageError("Invalid config statement: %r, should be Class.trait = value" % line) + + + # otherwise, assume we are setting configurables. + # leave quotes on args when splitting, because we want + # unquoted args to eval in user_ns + cfg = Config() + exec "cfg."+line in locals(), self.user_ns + + for configurable in self.configurables: + try: + configurable.update_config(cfg) + except Exception as e: + error(e) + # end Magic diff --git a/IPython/lib/pylabtools.py b/IPython/lib/pylabtools.py index 8b25a8c..63b915e 100644 --- a/IPython/lib/pylabtools.py +++ b/IPython/lib/pylabtools.py @@ -257,6 +257,8 @@ def import_pylab(user_ns, backend, import_all=True, shell=None): cfg = InlineBackendConfig.instance(config=shell.config) cfg.shell = shell + if cfg not in shell.configurables: + shell.configurables.append(cfg) if backend == backends['inline']: from IPython.zmq.pylab.backend_inline import flush_figures