Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

%config magic #923

Merged
merged 10 commits into from

3 participants

@minrk
Owner

should close #903

Adds %config magic, which allows %config Foo.bar = 5 configuration of IPython configurables.

The Magic class keeps a list of configurables which will be updated by the change, so any objects that should be accessible to this magic should be appended to shell.configurables. I started with everything I saw as configurable in InteractiveShell.

Usage

Use just %config to see what classes are available, and %config Class to get the trait info for that class.

When setting values via%config Class.trait = value It is evaluated with user_ns in globals, so you can do arbitrary things like:

In [4]: default = 'png'

In [5]: %config InlineBackendConfig.figure_format = raw_input('what figure format should we use? ') or default

Of course, this magic reveals just how much we don't use traits/config properly. Almost everything is attached to the InteractiveShell object, and has an effect exactly once during an init_foo() method, rather than allowing config propagation via _trait_changed() methods.

For instance, IPCompleter has an omit__names attribute, but the configurable is InteractiveShell.readline_omit__names, which is clearly wrong.

We've done a good job with config in new code, but I think existing code needs a pretty hefty pass to get configurables attached to the right objects, and getting logic like %colors into shell._colors_changed.

@minrk
Owner

Moving discussion from #903 to here (PR), pinging @fperez and @ellisonbg to keep conversation updates linked up.

I've renamed InlineBackendConfig -> InlineBackend (with warning on old name, for any of those still lingering on it).

Here's a quick question: Should we switch the inline figure default back to svg from png? PNG is the default, because it's a good deal sharper, and for figure snobs it does look better than SVG. However, it is less capable, in that the SVG+XHTML export will lack figures in the default state (see #735). Since it's easy to change the figure format, maybe we should change the default to the more capable one, and let the nicer-looking format be configurable?

A possible issue would be that the svg dpi is tuned such that svg and png figures are the same size in the QtConsole, but I find that they are not the same in a browser using the notebook, and the png size is more sensible. It is also true that png is just a much more portable and reliable (if not editable) format.

@minrk
Owner

I updated some docs, to cover using the %config magic to configure the inline backend, and moved the completer configurables to the completer class, where they belong.

@ellisonbg
Owner

@fperez will probably have thoughts on what image format should be default. I am fine moving to png and it does look nicer in many cases. Also, having it as the default will bring png bugs in matplotlib to light more readily.

There may be some browser tuning we can/should do to make the figure sizes of png/svg the same.

@minrk
Owner

@ellisonbg - I should clarify. The default is png, because it looks better. I'm wondering if we should change it to svg because some functionality (xhtml export) is unavailable with the default.

@fperez
Owner
@ellisonbg
Owner

@minrk: oops, that was a brain typo, I do realize the default in png. I am fine moving to svg given the support in browsers is much better than the qt console.

@fperez
Owner

@minrk, note that I'm getting a failure in the test suite when I merge this onto master:

======================================================================
FAIL: Doctest: IPython.core.magic.Magic.magic_config
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/fperez/usr/lib/python2.6/site-packages/IPython/testing/plugin/ipdoctest.py", line 265, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for IPython.core.magic.Magic.magic_config
  File "/home/fperez/usr/lib/python2.6/site-packages/IPython/core/magic.py", line 3627, in magic_config

----------------------------------------------------------------------
File "/home/fperez/usr/lib/python2.6/site-packages/IPython/core/magic.py", line 3657, in IPython.core.magic.Magic.magic_config
Failed example:
    get_ipython().magic(u"config IPCompleter")
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python2.6/doctest.py", line 1253, in __run
        compileflags, 1) in test.globs
      File "<doctest IPython.core.magic.Magic.magic_config[1]>", line 1, in <module>
        get_ipython().magic(u"config IPCompleter")
      File "/home/fperez/usr/lib/python2.6/site-packages/IPython/core/interactiveshell.py", line 1998, in magic
        result = fn(magic_args)
      File "/home/fperez/usr/lib/python2.6/site-packages/IPython/core/magic.py", line 3707, in magic_config
        help = re.sub(r'^\-\-', '', help, flags=re.MULTILINE)
    TypeError: sub() got an unexpected keyword argument 'flags'

>>  raise self.failureException(self.format_failure(<StringIO.StringIO instance at 0x4482cb0>.getvalue()))

Do you see it too? If not, we can try to debug it together on my box... Problem seen on python 2.6, ubuntu 10.10, 64 bit.

@fperez
Owner

ps - I think if you want to pass flags in a 2.6-compatible manner to a regexp, you must compile it and then use the .sub() method of the compiled regexp. In 2.6, the re module doesn't support flags in the methods. The signature for re.sub changed:

2.6:

re.sub(pattern, repl, string[, count])

2.7:

re.sub(pattern, repl, string[, count, flags])
@minrk
Owner

good catch, I didn't realize it had changed. I'll compile&call.

@minrk
Owner

regex is now compiled, should work on 2.6.

@fperez
Owner

Heads-up @minrk: this one popped a conflict after I just merged the read-only branch... Can you give it a quick rebase? I was about to work on it and saw the conflicts...

minrk added some commits
@minrk minrk move useful update_config method to Configurable from Application
This method should be used whenever updating the config of an object.
It is useful for all configurables, not just Applications.
8706608
@minrk minrk allow using instance values in place of defaults in Configurable.clas…
…s_get_help
66f74cc
@minrk minrk add %config magic for configuring IPython 63ad149
@minrk minrk filter %config class list to exclude classes with no configurable traits 8837523
@minrk minrk Rename InlineBackendConfig -> InlineBackend
include deprecation warning on old name
74b5624
@minrk minrk DisplayFormatter.formatters should not be configurable
it is a dict of instances, which are not allowed in config
f960771
@minrk minrk add reference to `%config InlineBackend` in %pylab docstring
also cleaned up %config and %pylab docstrings to be a little more sphinx-autogen friendly.
7e64be7
@minrk minrk update qtconsole doc with discussion of InlineBackend config 859e6ae
@minrk minrk move completer configurables to IPCompleter where they belong
* InteractiveShell.readline_omit__names -> IPCompleter.omit__names
* InteractiveShell.readline_merge_completions -> IPCompleter.merge_completions

add test for IPCompleter.omit__names, which also covers IPCompleter
as a configurable.

update %config doctest to match, and replace Completer with IPCompleter
in TerminalIPythonApp.classes
860949d
@minrk minrk compile sub expr in %config for 2.6 compatibility 1cec181
@minrk
Owner

rebased - tiny conflict with PR #921.

@fperez
Owner

Looks good, ran lots of tests on 2.6 and 2.7, via screen and normal logins. After some initial weird glitching, that went away with a pyc cleanout, all looks good now so I think it's good to merge.

I'm going to leave the image default discussion to happen separately so we don't hold this PR forever, made #944 for that.

Merging now, thanks for the great work! This wil be very useful.

Final comment: adding mention of %config to the main configuration section in the docs is probably a good idea. Since that would be a docs-only patch, just go ahead and commit it any time if you get a chance (and if you can't do it now, let me know and I can take a crack at it later). But I'll merge the code now.

@fperez fperez merged commit b725362 into ipython:master
@fperez fperez referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 29, 2011
  1. @minrk

    move useful update_config method to Configurable from Application

    minrk authored
    This method should be used whenever updating the config of an object.
    It is useful for all configurables, not just Applications.
  2. @minrk
  3. @minrk
  4. @minrk
  5. @minrk

    Rename InlineBackendConfig -> InlineBackend

    minrk authored
    include deprecation warning on old name
  6. @minrk

    DisplayFormatter.formatters should not be configurable

    minrk authored
    it is a dict of instances, which are not allowed in config
  7. @minrk

    add reference to `%config InlineBackend` in %pylab docstring

    minrk authored
    also cleaned up %config and %pylab docstrings to be a little more sphinx-autogen friendly.
  8. @minrk
  9. @minrk

    move completer configurables to IPCompleter where they belong

    minrk authored
    * InteractiveShell.readline_omit__names -> IPCompleter.omit__names
    * InteractiveShell.readline_merge_completions -> IPCompleter.merge_completions
    
    add test for IPCompleter.omit__names, which also covers IPCompleter
    as a configurable.
    
    update %config doctest to match, and replace Completer with IPCompleter
    in TerminalIPythonApp.classes
  10. @minrk
This page is out of date. Refresh to see the latest.
View
55 IPython/config/configurable.py
@@ -138,35 +138,58 @@ def _config_changed(self, name, old, new):
# shared by all instances, effectively making it a class attribute.
setattr(self, k, deepcopy(config_value))
+ def update_config(self, config):
+ """Fire the traits events when the config is updated."""
+ # Save a copy of the current config.
+ newconfig = deepcopy(self.config)
+ # Merge the new config into the current one.
+ newconfig._merge(config)
+ # Save the combined config as self.config, which triggers the traits
+ # events.
+ self.config = newconfig
+
@classmethod
- def class_get_help(cls):
- """Get the help string for this class in ReST format."""
+ def class_get_help(cls, inst=None):
+ """Get the help string for this class in ReST format.
+
+ If `inst` is given, it's current trait values will be used in place of
+ class defaults.
+ """
+ assert inst is None or isinstance(inst, cls)
cls_traits = cls.class_traits(config=True)
final_help = []
final_help.append(u'%s options' % cls.__name__)
final_help.append(len(final_help[0])*u'-')
for k,v in cls.class_traits(config=True).iteritems():
- help = cls.class_get_trait_help(v)
+ help = cls.class_get_trait_help(v, inst)
final_help.append(help)
return '\n'.join(final_help)
@classmethod
- def class_get_trait_help(cls, trait):
- """Get the help string for a single trait."""
+ def class_get_trait_help(cls, trait, inst=None):
+ """Get the help string for a single trait.
+
+ If `inst` is given, it's current trait values will be used in place of
+ the class default.
+ """
+ assert inst is None or isinstance(inst, cls)
lines = []
header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__)
lines.append(header)
- try:
- dvr = repr(trait.get_default_value())
- except Exception:
- dvr = None # ignore defaults we can't construct
- if dvr is not None:
- if len(dvr) > 64:
- dvr = dvr[:61]+'...'
- lines.append(indent('Default: %s'%dvr, 4))
+ if inst is not None:
+ lines.append(indent('Current: %r' % getattr(inst, trait.name), 4))
+ else:
+ try:
+ dvr = repr(trait.get_default_value())
+ except Exception:
+ dvr = None # ignore defaults we can't construct
+ if dvr is not None:
+ if len(dvr) > 64:
+ dvr = dvr[:61]+'...'
+ lines.append(indent('Default: %s' % dvr, 4))
if 'Enum' in trait.__class__.__name__:
# include Enum choices
- lines.append(indent('Choices: %r'%(trait.values,)))
+ lines.append(indent('Choices: %r' % (trait.values,)))
help = trait.get_metadata('help')
if help is not None:
@@ -175,9 +198,9 @@ def class_get_trait_help(cls, trait):
return '\n'.join(lines)
@classmethod
- def class_print_help(cls):
+ def class_print_help(cls, inst=None):
"""Get the help string for a single trait and print it."""
- print cls.class_get_help()
+ print cls.class_get_help(inst)
@classmethod
def class_config_section(cls):
View
13 IPython/config/tests/test_configurable.py
@@ -53,6 +53,15 @@ class MyConfigurable(Configurable):
Default: 1.0
The integer b."""
+mc_help_inst=u"""MyConfigurable options
+----------------------
+--MyConfigurable.a=<Int>
+ Current: 5
+ The integer a.
+--MyConfigurable.b=<Float>
+ Current: 4.0
+ The integer b."""
+
class Foo(Configurable):
a = Int(0, config=True, help="The integer a.")
b = Unicode('nope', config=True)
@@ -139,6 +148,10 @@ def test_override2(self):
def test_help(self):
self.assertEquals(MyConfigurable.class_get_help(), mc_help)
+ def test_help_inst(self):
+ inst = MyConfigurable(a=5, b=4)
+ self.assertEquals(MyConfigurable.class_get_help(inst), mc_help_inst)
+
class TestSingletonConfigurable(TestCase):
View
39 IPython/core/completer.py
@@ -85,7 +85,7 @@
from IPython.utils import io
from IPython.utils.dir2 import dir2
from IPython.utils.process import arg_split
-from IPython.utils.traitlets import CBool
+from IPython.utils.traitlets import CBool, Enum
#-----------------------------------------------------------------------------
# Globals
@@ -276,8 +276,9 @@ class Completer(Configurable):
but can be unsafe because the code is actually evaluated on TAB.
"""
)
+
- def __init__(self, namespace=None, global_namespace=None, config=None):
+ def __init__(self, namespace=None, global_namespace=None, config=None, **kwargs):
"""Create a new completer for the command line.
Completer(namespace=ns,global_namespace=ns2) -> completer instance.
@@ -311,7 +312,7 @@ def __init__(self, namespace=None, global_namespace=None, config=None):
else:
self.global_namespace = global_namespace
- super(Completer, self).__init__(config=config)
+ super(Completer, self).__init__(config=config, **kwargs)
def complete(self, text, state):
"""Return the next possible completion for 'text'.
@@ -417,10 +418,30 @@ def _greedy_changed(self, name, old, new):
if self.readline:
self.readline.set_completer_delims(self.splitter.get_delims())
+
+ merge_completions = CBool(True, config=True,
+ help="""Whether to merge completion results into a single list
+
+ If False, only the completion results from the first non-empty
+ completer will be returned.
+ """
+ )
+ omit__names = Enum((0,1,2), default_value=2, config=True,
+ help="""Instruct the completer to omit private method names
+
+ Specifically, when completing on ``object.<tab>``.
+
+ When 2 [default]: all names that start with '_' will be excluded.
+
+ When 1: all 'magic' names (``__foo__``) will be excluded.
+
+ When 0: nothing will be excluded.
+ """
+ )
def __init__(self, shell=None, namespace=None, global_namespace=None,
- omit__names=True, alias_table=None, use_readline=True,
- config=None):
+ alias_table=None, use_readline=True,
+ config=None, **kwargs):
"""IPCompleter() -> completer
Return a completer object suitable for use by the readline library
@@ -438,10 +459,6 @@ def __init__(self, shell=None, namespace=None, global_namespace=None,
handle cases (such as IPython embedded inside functions) where
both Python scopes are visible.
- - The optional omit__names parameter sets the completer to omit the
- 'magic' names (__magicname__) for python objects unless the text
- to be completed explicitly starts with one or more underscores.
-
- If alias_table is supplied, it should be a dictionary of aliases
to complete.
@@ -463,12 +480,10 @@ def __init__(self, shell=None, namespace=None, global_namespace=None,
# _greedy_changed() depends on splitter and readline being defined:
Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
- config=config)
+ config=config, **kwargs)
# List where completion matches will be stored
self.matches = []
- self.omit__names = omit__names
- self.merge_completions = shell.readline_merge_completions
self.shell = shell.shell
if alias_table is None:
alias_table = {}
View
2  IPython/core/formatters.py
@@ -44,7 +44,7 @@ class DisplayFormatter(Configurable):
# A dict of formatter whose keys are format types (MIME types) and whose
# values are subclasses of BaseFormatter.
- formatters = Dict(config=True)
+ formatters = Dict()
def _formatters_default(self):
"""Activate the default formatters."""
formatter_classes = [
View
15 IPython/core/interactiveshell.py
@@ -322,8 +322,6 @@ def _exiter_default(self):
# The readline stuff will eventually be moved to the terminal subclass
# but for now, we can't do that as readline is welded in everywhere.
readline_use = CBool(True, config=True)
- readline_merge_completions = CBool(True, config=True)
- readline_omit__names = Enum((0,1,2), default_value=2, config=True)
readline_remove_delims = Unicode('-/~', config=True)
# don't use \M- bindings by default, because they
# conflict with 8-bit encodings. See gh-58,gh-88
@@ -379,6 +377,7 @@ def __init__(self, config=None, ipython_dir=None, profile_dir=None,
# 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 +601,11 @@ def init_prompts(self):
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 +621,7 @@ def init_displayhook(self):
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 +1437,7 @@ def object_inspect(self, oname):
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)
@@ -1851,11 +1854,11 @@ def init_completer(self):
self.Completer = IPCompleter(shell=self,
namespace=self.user_ns,
global_namespace=self.user_global_ns,
- omit__names=self.readline_omit__names,
alias_table=self.alias_manager.alias_table,
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 +2115,7 @@ def getoutput(self, cmd, split=True):
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 +2124,12 @@ def init_alias(self):
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 +2137,7 @@ def init_plugin_manager(self):
def init_payload(self):
self.payload_manager = PayloadManager(config=self.config)
+ self.configurables.append(self.payload_manager)
#-------------------------------------------------------------------------
# Things related to the prefilter
@@ -2137,6 +2145,7 @@ def init_payload(self):
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).
View
136 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 @@ def __init__(self,shell):
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()
@@ -3451,6 +3455,17 @@ def magic_pylab(self, s):
It will import at the top level numpy as np, pyplot as plt, matplotlib,
pylab and mlab, as well as all names from numpy and pylab.
+ If you are using the inline matplotlib backend for embedded figures,
+ you can adjust its behavior via the %config magic::
+
+ # enable SVG figures, necessary for SVG+XHTML export in the qtconsole
+ In [1]: %config InlineBackend.figure_format = 'svg'
+
+ # change the behavior of closing all figures at the end of each
+ # execution (cell), or allowing reuse of active figures across
+ # cells:
+ In [2]: %config InlineBackend.close_figures = False
+
Parameters
----------
guiname : optional
@@ -3461,19 +3476,21 @@ def magic_pylab(self, s):
Examples
--------
- In this case, where the MPL default is TkAgg:
- In [2]: %pylab
+ In this case, where the MPL default is TkAgg::
+
+ In [2]: %pylab
- Welcome to pylab, a matplotlib-based Python environment.
- Backend in use: TkAgg
- For more information, type 'help(pylab)'.
+ Welcome to pylab, a matplotlib-based Python environment.
+ Backend in use: TkAgg
+ For more information, type 'help(pylab)'.
- But you can explicitly request a different backend:
- In [3]: %pylab qt
+ But you can explicitly request a different backend::
- Welcome to pylab, a matplotlib-based Python environment.
- Backend in use: Qt4Agg
- For more information, type 'help(pylab)'.
+ In [3]: %pylab qt
+
+ Welcome to pylab, a matplotlib-based Python environment.
+ Backend in use: Qt4Agg
+ For more information, type 'help(pylab)'.
"""
if Application.initialized():
@@ -3607,4 +3624,103 @@ def magic_notebook(self, s):
with open(new_fname, 'w') as f:
current.write(nb, f, new_format)
+ def magic_config(self, s):
+ """configure IPython
+
+ %config Class[.trait=value]
+
+ 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
+
+ To view what is configurable on a given class, just pass the class name::
+
+ In [2]: %config IPCompleter
+ IPCompleter options
+ -----------------
+ IPCompleter.omit__names=<Enum>
+ Current: 2
+ Choices: (0, 1, 2)
+ Instruct the completer to omit private method names
+ Specifically, when completing on ``object.<tab>``.
+ When 2 [default]: all names that start with '_' will be excluded.
+ When 1: all 'magic' names (``__foo__``) will be excluded.
+ When 0: nothing will be excluded.
+ IPCompleter.merge_completions=<CBool>
+ Current: True
+ Whether to merge completion results into a single list
+ If False, only the completion results from the first non-empty completer
+ will be returned.
+ IPCompleter.greedy=<CBool>
+ 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
+ # get list of class names for configurables that have someting to configure:
+ classnames = [ c.__class__.__name__ for c in self.configurables if c.__class__.class_traits(config=True) ]
+ 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(re.compile(r'^--', re.MULTILINE), '', help)
+ 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
View
25 IPython/core/tests/test_completer.py
@@ -13,6 +13,7 @@
import nose.tools as nt
# our own packages
+from IPython.config.loader import Config
from IPython.core import completer
from IPython.external.decorators import knownfailureif
from IPython.utils.tempdir import TemporaryDirectory
@@ -205,3 +206,27 @@ def test_greedy_completions():
_,c = ip.complete('.',line='a[0].')
nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
+def test_omit__names():
+ # also happens to test IPCompleter as a configurable
+ ip = get_ipython()
+ ip._hidden_attr = 1
+ c = ip.Completer
+ ip.ex('ip=get_ipython()')
+ cfg = Config()
+ cfg.IPCompleter.omit__names = 0
+ c.update_config(cfg)
+ s,matches = c.complete('ip.')
+ nt.assert_true('ip.__str__' in matches)
+ nt.assert_true('ip._hidden_attr' in matches)
+ cfg.IPCompleter.omit__names = 1
+ c.update_config(cfg)
+ s,matches = c.complete('ip.')
+ nt.assert_false('ip.__str__' in matches)
+ nt.assert_true('ip._hidden_attr' in matches)
+ cfg.IPCompleter.omit__names = 2
+ c.update_config(cfg)
+ s,matches = c.complete('ip.')
+ nt.assert_false('ip.__str__' in matches)
+ nt.assert_false('ip._hidden_attr' in matches)
+ del ip._hidden_attr
+
View
4 IPython/frontend/terminal/ipapp.py
@@ -35,7 +35,7 @@
from IPython.config.application import boolean_flag, catch_config_error
from IPython.core import release
from IPython.core import usage
-from IPython.core.completer import Completer
+from IPython.core.completer import IPCompleter
from IPython.core.crashhandler import CrashHandler
from IPython.core.formatters import PlainTextFormatter
from IPython.core.application import (
@@ -199,7 +199,7 @@ def _classes_default(self):
TerminalInteractiveShell,
ProfileDir,
PlainTextFormatter,
- Completer,
+ IPCompleter,
]
subcommands = Dict(dict(
View
6 IPython/lib/pylabtools.py
@@ -253,10 +253,12 @@ def import_pylab(user_ns, backend, import_all=True, shell=None):
# function that will pick up the results for display. This can only be
# done with access to the real shell object.
#
- from IPython.zmq.pylab.backend_inline import InlineBackendConfig
+ from IPython.zmq.pylab.backend_inline import InlineBackend
- cfg = InlineBackendConfig.instance(config=shell.config)
+ cfg = InlineBackend.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
View
19 IPython/zmq/pylab/backend_inline.py
@@ -18,13 +18,24 @@
from IPython.core.displaypub import publish_display_data
from IPython.lib.pylabtools import print_figure, select_figure_format
from IPython.utils.traitlets import Dict, Instance, CaselessStrEnum, CBool
+from IPython.utils.warn import warn
+
#-----------------------------------------------------------------------------
# Configurable for inline backend options
#-----------------------------------------------------------------------------
-
+# inherit from InlineBackendConfig for deprecation purposes
class InlineBackendConfig(SingletonConfigurable):
+ pass
+
+class InlineBackend(InlineBackendConfig):
"""An object to store configuration of the inline backend."""
+ def _config_changed(self, name, old, new):
+ # warn on change of renamed config section
+ if new.InlineBackendConfig != old.InlineBackendConfig:
+ warn("InlineBackendConfig has been renamed to InlineBackend")
+ super(InlineBackend, self)._config_changed(name, old, new)
+
# The typical default figure size is too large for inline use,
# so we shrink the figure size to 6x4, and tweak fonts to
# make that fit. This is configurable via Global.pylab_inline_rc,
@@ -83,7 +94,7 @@ def show(close=None):
removed from the internal list of figures.
"""
if close is None:
- close = InlineBackendConfig.instance().close_figures
+ close = InlineBackend.instance().close_figures
for figure_manager in Gcf.get_all_fig_managers():
send_figure(figure_manager.canvas.figure)
if close:
@@ -129,7 +140,7 @@ def flush_figures():
if not show._draw_called:
return
- if InlineBackendConfig.instance().close_figures:
+ if InlineBackend.instance().close_figures:
# ignore the tracking, just draw and close all figures
return show(True)
@@ -149,7 +160,7 @@ def send_figure(fig):
# big blank spaces in the qt console
if not fig.axes:
return
- fmt = InlineBackendConfig.instance().figure_format
+ fmt = InlineBackend.instance().figure_format
data = print_figure(fig, fmt)
mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
mime = mimetypes[fmt]
View
67 docs/source/interactive/qtconsole.txt
@@ -120,6 +120,56 @@ calling :func:`display`, you can specify ``--pylab=inline`` when you start the
console, and each time you make a plot, it will show up in your document, as if
you had called :func:`display(fig)`.
+The inline backend can use either SVG or PNG figures (PNG being the default).
+To switch between them, set the ``InlineBackend.figure_format`` configurable
+in a config file, or via the ``%config`` magic:
+
+.. sourcecode:: ipython
+
+ In [10]: %config InlineBackend.figure_format = 'svg'
+
+.. note::
+
+ Changing the inline figure format also affects calls to :func:`display` above,
+ even if you are not using the inline backend for all figures.
+
+By default, IPython closes all figures at the completion of each execution. This means you
+don't have to manually close figures, which is less convenient when figures aren't attached
+to windows with an obvious close button. It also means that the first matplotlib call in
+each cell will always create a new figure:
+
+.. sourcecode:: ipython
+
+ In [11]: plot(range(100))
+ <single-line plot>
+
+ In [12]: plot([1,3,2])
+ <another single-line plot>
+
+
+However, it does prevent the list of active figures surviving from one input cell to the
+next, so if you want to continue working with a figure, you must hold on to a reference to
+it:
+
+.. sourcecode:: ipython
+
+ In [11]: fig = gcf()
+ ....: fig.plot(rand(100))
+ <plot>
+ In [12]: fig.title('Random Title')
+ <redraw plot with title>
+
+This behavior is controlled by the :attr:`InlineBackend.close_figures` configurable, and
+if you set it to False, via %config or config file, then IPython will *not* close figures,
+and tools like :func:`gcf`, :func:`gca`, :func:`getfigs` will behave the same as they
+do with other backends. You will, however, have to manually close figures:
+
+.. sourcecode:: ipython
+
+ # close all active figures:
+ In [13]: [ fig.close() for fig in getfigs() ]
+
+
.. _saving:
@@ -132,6 +182,22 @@ will be PNG in HTML, or inlined as SVG in XHTML. PNG images have the option to
be either in an external folder, as in many browsers' "Webpage, Complete"
option, or inlined as well, for a larger, but more portable file.
+.. note::
+
+ Export to SVG+XHTML requires that you are using SVG figures, which is *not*
+ the default. To switch the inline figure format to use SVG during an active
+ session, do:
+
+ .. sourcecode:: ipython
+
+ In [10]: %config InlineBackend.figure_format = 'svg'
+
+ Or, you can add the same line (c.Inline... instead of %config Inline...) to
+ your config files.
+
+ This will only affect figures plotted after making this call
+
+
The widget also exposes the ability to print directly, via the default print
shortcut or context menu.
@@ -146,6 +212,7 @@ See these examples of :download:`png/html<figs/jn.html>` and
:download:`svg/xhtml <figs/jn.xhtml>` output. Note that syntax highlighting
does not survive export. This is a known issue, and is being investigated.
+
Colors and Highlighting
=======================
Something went wrong with that request. Please try again.