Repository: ipython/ipython (Python)

Issue:
Error in IPython 5.6: MPLBACKEND=PS and importing matplotlib.pyplot
There's seems to be a problem if `MPLBACKEND=PS` and if an IPython script imports `matplotlib.pyplot` (`import matplotlib` is still fine). This arises starting with IPython 5.6 (5.5 is fine), so my best guess is that it was caused by #10868 -- at least, I don't see any other likely suspects. 

To reproduce:

```bash
MPLBACKEND=PS ipython -c "import matplotlib.pyplot"
```

```pytb
---------------------------------------------------------------------------
UnknownBackend                            Traceback (most recent call last)
<ipython-input-1-864e826dab68> in <module>()
----> 1 import matplotlib.pyplot

/home/dwhs/miniconda2/lib/python2.7/site-packages/matplotlib/pyplot.py in <module>()
   2607 # are no-ops and the registered function respect `mpl.is_interactive()`
   2608 # to determine if they should trigger a draw.
-> 2609 install_repl_displayhook()
   2610
   2611 ################# REMAINING CONTENT GENERATED BY boilerplate.py ##############

/home/dwhs/miniconda2/lib/python2.7/site-packages/matplotlib/pyplot.py in install_repl_displayhook()
    164             ipython_gui_name = backend2gui.get(get_backend())
    165             if ipython_gui_name:
--> 166                 ip.enable_gui(ipython_gui_name)
    167         else:
    168             _INSTALL_FIG_OBSERVER = True

/home/dwhs/miniconda2/lib/python2.7/site-packages/IPython/terminal/interactiveshell.pyc in enable_gui(self, gui)
    514         if gui:
    515             self.active_eventloop, self._inputhook =\
--> 516                 get_inputhook_name_and_func(gui)
    517         else:
    518             self.active_eventloop = self._inputhook = None

/home/dwhs/miniconda2/lib/python2.7/site-packages/IPython/terminal/pt_inputhooks/__init__.pyc in get_inputhook_name_and_func(gui)
     36
     37     if gui not in backends:
---> 38         raise UnknownBackend(gui)
     39
     40     if gui in aliases:

UnknownBackend: No event loop integration for 'ps'. Supported event loops are: qt, qt4, qt5, gtk, gtk2, gtk3, tk, wx, pyglet, glut, osx
Error in callback <function post_execute at 0x7f9a1f366578> (for post_execute):
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/dwhs/miniconda2/lib/python2.7/site-packages/matplotlib/pyplot.py in post_execute()
    146
    147             def post_execute():
--> 148                 if matplotlib.is_interactive():
    149                     draw_all()
    150

AttributeError: 'NoneType' object has no attribute 'is_interactive'
```

In practice, this is causing us trouble because we're using it within a CI script that includes both straight Python (where we want `MPLBACKEND=PS`) and a notebook runner (https://github.com/jhprinz/ipynb-test), where some notebooks don't use matplotlib. When we import a package that in turn imports matplotlib, we get errors, e.g., https://gitlab.e-cam2020.eu:10443/dwhswenson/ops_additional_examples/-/jobs/3991. For now, our fix is to set `MPLBACKEND=PS` only when running the pure Python scripts that need it.


Discussion:
@tacaswell I think this is relevant to your work in #10868 (which added ps as a key in backend2gui). Can you take a look?
Yup, see the problem, will have PR shortly
That's my favourite kind of answer! :grinning: 



Patch:
diff --git a/IPython/core/pylabtools.py b/IPython/core/pylabtools.py
index 7f275a92a04..4423ed5d408 100644
--- a/IPython/core/pylabtools.py
+++ b/IPython/core/pylabtools.py
@@ -46,6 +46,9 @@
 # And some backends that don't need GUI integration
 del backend2gui['nbAgg']
 del backend2gui['agg']
+del backend2gui['svg']
+del backend2gui['pdf']
+del backend2gui['ps']
 del backend2gui['module://ipykernel.pylab.backend_inline']
 
 #-----------------------------------------------------------------------------


Test patch:
diff --git a/IPython/core/tests/test_pylabtools.py b/IPython/core/tests/test_pylabtools.py
index 71dd7377885..181e99f9b84 100644
--- a/IPython/core/tests/test_pylabtools.py
+++ b/IPython/core/tests/test_pylabtools.py
@@ -105,7 +105,7 @@ def test_select_figure_formats_kwargs():
     f = formatter.lookup_by_type(Figure)
     cell = f.__closure__[0].cell_contents
     nt.assert_equal(cell, kwargs)
-    
+
     # check that the formatter doesn't raise
     fig = plt.figure()
     ax = fig.add_subplot(1,1,1)
@@ -150,7 +150,7 @@ class TestPylabSwitch(object):
     class Shell(InteractiveShell):
         def enable_gui(self, gui):
             pass
-    
+
     def setup(self):
         import matplotlib
         def act_mpl(backend):
@@ -244,3 +244,7 @@ def test_qt_gtk(self):
         nt.assert_equal(gui, 'qt')
         nt.assert_equal(s.pylab_gui_select, 'qt')
 
+
+def test_no_gui_backends():
+    for k in ['agg', 'svg', 'pdf', 'ps']:
+        assert k not in pt.backend2gui