Repository: ipython/ipython

Issue:
bad message when %pylab fails due import *other* than matplotlib
this is just to capture an issue that was sent to IPython-User by 
@michaelaye:

> I know you guys are busy getting a release on 1.0 done, so here's some 
> feedback trying to use git master:
> 
> In version
> rel-0.13-3590-gadb77e3
> matplotlib is not found, even so it is importable, so when using pylab 
> mode I get an error message:
> 
> Python 2.7.3 |EPD 7.3-2 (64-bit)| (default, Apr 12 2012, 11:14:05)
> Type "copyright", "credits" or "license" for more information.
> 
> IPython 1.0.dev -- An enhanced Interactive Python.
> ?         -> Introduction and overview of IPython's features.
> %quickref -> Quick reference.
> help      -> Python's own help system.
> object?   -> Details about 'object', use 'object??' for extra details.
> 
> In [1]: import matplotlib
> 
> In [2]: pylab
> ERROR: pylab mode doesn't work as matplotlib could not be found.
> Is it installed on the system?
> 
> And since version ((rel-0.13-3681-g123ae5a)) up to now I get an import 
> error for the sip module (using --pylab=qt)
> 
> ImportError: No module named sip
> 
> Michael



Discussion:

Resolving patch:
diff --git a/IPython/core/display.py b/IPython/core/display.py
--- a/IPython/core/display.py
+++ b/IPython/core/display.py
@@ -22,7 +22,7 @@
 import os
 import struct
 
-from IPython.utils.py3compat import string_types
+from IPython.utils.py3compat import string_types, cast_bytes_py2, cast_unicode
 
 from .displaypub import publish_display_data
 
@@ -377,6 +377,7 @@ def data(self, svg):
             return
         # parse into dom object
         from xml.dom import minidom
+        svg = cast_bytes_py2(svg)
         x = minidom.parseString(svg)
         # get svg tag (should be 1)
         found_svg = x.getElementsByTagName('svg')
@@ -386,6 +387,7 @@ def data(self, svg):
             # fallback on the input, trust the user
             # but this is probably an error.
             pass
+        svg = cast_unicode(svg)
         self._data = svg
 
     def _repr_svg_(self):
diff --git a/IPython/core/magics/pylab.py b/IPython/core/magics/pylab.py
--- a/IPython/core/magics/pylab.py
+++ b/IPython/core/magics/pylab.py
@@ -82,20 +82,7 @@ def matplotlib(self, line=''):
         '--no-import-all', action='store_true', default=None,
         help="""Prevent IPython from performing ``import *`` into the interactive namespace.
         
-        The names that will still be added to the namespace if this flag is given::
-        
-            numpy
-            matplotlib
-            np (numpy alias)
-            plt (matplotlib.pyplot alias)
-            pylab (from matplotlib)
-            pyplot (from matplotlib)
-            mlab (from matplotlib)
-            display (from IPython)
-            figsize (from IPython)
-            getfigs (from IPython)
-        
-        You can govern the default behavior with the
+        You can govern the default behavior of this flag with the
         InteractiveShellApp.pylab_import_all configurable.
         """
     )
@@ -105,11 +92,25 @@ def pylab(self, line=''):
 
         This function lets you activate pylab (matplotlib, numpy and
         interactive support) at any point during an IPython session.
-
-        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.
         
-        See the %matplotlib magic for more details.
+        %pylab makes the following imports::
+        
+            import numpy
+            import matplotlib
+            from matplotlib import pylab, mlab, pyplot
+            np = numpy
+            plt = pyplot
+            
+            from IPython.display import display
+            from IPython.core.pylabtools import figsize, getfigs
+            
+            from pylab import *
+            from numpy import *
+
+        If you pass `--no-import-all`, the last two `*` imports will be excluded.
+        
+        See the %matplotlib magic for more details about activating matplotlib
+        without affecting the interactive namespace.
         """
         args = magic_arguments.parse_argstring(self.pylab, line)
         if args.no_import_all is None:
@@ -129,6 +130,7 @@ def pylab(self, line=''):
 
         gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
         self._show_matplotlib_backend(args.gui, backend)
+        print ("Populating the interactive namespace from numpy and matplotlib")
         if clobbered:
             warn("pylab import has clobbered these variables: %s"  % clobbered +
             "\n`%pylab --no-import-all` prevents importing * from pylab and numpy"
@@ -137,5 +139,5 @@ def pylab(self, line=''):
     def _show_matplotlib_backend(self, gui, backend):
         """show matplotlib message backend message"""
         if not gui or gui == 'auto':
-            print ("using matplotlib backend: %s" % backend)
+            print ("Using matplotlib backend: %s" % backend)
     
diff --git a/IPython/core/shellapp.py b/IPython/core/shellapp.py
--- a/IPython/core/shellapp.py
+++ b/IPython/core/shellapp.py
@@ -41,6 +41,9 @@
 # Aliases and Flags
 #-----------------------------------------------------------------------------
 
+backend_keys = sorted(pylabtools.backends.keys())
+backend_keys.insert(0, 'auto')
+
 shell_flags = {}
 
 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
@@ -103,6 +106,11 @@
     """Pre-load matplotlib and numpy for interactive use with
     the default matplotlib backend."""
 )
+shell_flags['matplotlib'] = (
+    {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
+    """Configure matplotlib for interactive use with
+    the default matplotlib backend."""
+)
 
 # it's possible we don't want short aliases for *all* of these:
 shell_aliases = dict(
@@ -115,6 +123,7 @@
     ext='InteractiveShellApp.extra_extension',
     gui='InteractiveShellApp.gui',
     pylab='InteractiveShellApp.pylab',
+    matplotlib='InteractiveShellApp.matplotlib',
 )
 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
 
@@ -169,7 +178,12 @@ def _extra_extension_changed(self, name, old, new):
     gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx'), config=True,
         help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx')."
     )
-    pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
+    matplotlib = CaselessStrEnum(backend_keys,
+        config=True,
+        help="""Configure matplotlib for interactive use with
+        the default matplotlib backend."""
+    )
+    pylab = CaselessStrEnum(backend_keys,
         config=True,
         help="""Pre-load matplotlib and numpy for interactive use,
         selecting a particular matplotlib backend and loop integration.
@@ -194,27 +208,42 @@ def init_shell(self):
 
     def init_gui_pylab(self):
         """Enable GUI event loop integration, taking pylab into account."""
-        if self.gui or self.pylab:
-            shell = self.shell
-            try:
-                if self.pylab:
-                    gui, backend = pylabtools.find_gui_and_backend(self.pylab)
-                    self.log.info("Enabling GUI event loop integration, "
-                              "toolkit=%s, pylab=%s" % (gui, self.pylab))
-                    if self.pylab == "auto":
-                        print ("using matplotlib backend: %s" % backend)
-                    shell.enable_pylab(self.pylab, import_all=self.pylab_import_all)
-                else:
-                    self.log.info("Enabling GUI event loop integration, "
-                                  "toolkit=%s" % self.gui)
-                    shell.enable_gui(self.gui)
-            except ImportError:
-                self.log.warn("pylab mode doesn't work as matplotlib could not be found." + \
-                              "\nIs it installed on the system?")
-                self.shell.showtraceback()
-            except Exception:
-                self.log.warn("GUI event loop or pylab initialization failed")
-                self.shell.showtraceback()
+        enable = False
+        shell = self.shell
+        if self.pylab:
+            enable = shell.enable_pylab
+            key = self.pylab
+        elif self.matplotlib:
+            enable = shell.enable_matplotlib
+            key = self.matplotlib
+        elif self.gui:
+            enable = shell.enable_gui
+            key = self.gui
+        
+        if not enable:
+            return
+        
+        try:
+            r = enable(key)
+        except ImportError:
+            self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
+            self.shell.showtraceback()
+            return
+        except Exception:
+            self.log.warn("GUI event loop or pylab initialization failed")
+            self.shell.showtraceback()
+            return
+            
+        if isinstance(r, tuple):
+            gui, backend = r[:2]
+            self.log.info("Enabling GUI event loop integration, "
+                      "eventloop=%s, matplotlib=%s", gui, backend)
+            if key == "auto":
+                print ("using matplotlib backend: %s" % backend)
+        else:
+            gui = r
+            self.log.info("Enabling GUI event loop integration, "
+                      "eventloop=%s", gui)
 
     def init_extensions(self):
         """Load all IPython extensions in IPythonApp.extensions.


Test patch: