From 936674b40343f77b1b93d5c280134df6804caf0c Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Sun, 4 Aug 2019 20:18:21 -0700 Subject: [PATCH 1/6] FIX: Don't enable IPython integration if not entering REPL. IPython can also be used to simply run files; when this is the case we are not going to be interactive; and we do not want to enable the eventloop integration. Otherwise someone doing: $ ipython script.py Will simply see a window blink, as IPython will exit immediately instead of showing the window and exit. I'm not quite sure how to test that are we basically _want_ something to block forever and wait for user input; so no test added Closes: https://github.com/ipython/ipython/issues/11837 --- lib/matplotlib/backend_bases.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index dfa18b92079f..78cc065318e5 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1553,6 +1553,20 @@ def _draw(renderer): raise Done(renderer) return figure._cachedRenderer +def is_non_interactive_terminal_ipython(ip): + """ + Return whether we are in a a terminal IPython, but non interactive. + + When in _terminal_ IPython, ip.parent will have and `interact` attribute, + if this attribute is False we do not setup eventloop integration as the + user will _not_ interact with IPython. In all other case (ZMQKernel, or is + interactive), we do. + """ + return (hasattr(ip, 'parent') + and (ip.parent is not None) + and getattr(ip.parent, 'interact', None) is False) + + class FigureCanvasBase: """ The canvas the figure renders into. @@ -1649,9 +1663,13 @@ def _fix_ipython_backend2gui(cls): # Work around pylabtools.find_gui_and_backend always reading from # rcParamsOrig. orig_origbackend = mpl.rcParamsOrig["backend"] + try: mpl.rcParamsOrig["backend"] = mpl.rcParams["backend"] - ip.enable_matplotlib() + if is_non_interactive_terminal_ipython(ip): + pass + else: + ip.enable_matplotlib() finally: mpl.rcParamsOrig["backend"] = orig_origbackend From 4cde7304c2428c7156ea91a76d1484aa67055c4e Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 5 Aug 2019 08:59:58 -0400 Subject: [PATCH 2/6] MNT: rename helper to be private --- lib/matplotlib/backend_bases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 78cc065318e5..2d02a67e13ab 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1553,7 +1553,7 @@ def _draw(renderer): raise Done(renderer) return figure._cachedRenderer -def is_non_interactive_terminal_ipython(ip): +def _is_non_interactive_terminal_ipython(ip): """ Return whether we are in a a terminal IPython, but non interactive. @@ -1666,7 +1666,7 @@ def _fix_ipython_backend2gui(cls): try: mpl.rcParamsOrig["backend"] = mpl.rcParams["backend"] - if is_non_interactive_terminal_ipython(ip): + if _is_non_interactive_terminal_ipython(ip): pass else: ip.enable_matplotlib() From d66a7608485a84a62913bd5280862aa4cbbb43da Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 5 Aug 2019 09:00:20 -0400 Subject: [PATCH 3/6] FIX: preserve interactive state around ip.enable_matplotlib() closes #14950 --- lib/matplotlib/backend_bases.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 2d02a67e13ab..da4adabfcc37 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1669,7 +1669,12 @@ def _fix_ipython_backend2gui(cls): if _is_non_interactive_terminal_ipython(ip): pass else: - ip.enable_matplotlib() + was_interacive = mpl.is_interactive() + try: + ip.enable_matplotlib() + finally: + mpl.interactive(was_interacive) + finally: mpl.rcParamsOrig["backend"] = orig_origbackend From d762969a20ce91c592348a00ee555e4d227a15b7 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 5 Aug 2019 11:04:44 -0400 Subject: [PATCH 4/6] MNT: fix spelling of local variable --- lib/matplotlib/backend_bases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index da4adabfcc37..a94846f6e24c 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1669,11 +1669,11 @@ def _fix_ipython_backend2gui(cls): if _is_non_interactive_terminal_ipython(ip): pass else: - was_interacive = mpl.is_interactive() + was_interactive = mpl.is_interactive() try: ip.enable_matplotlib() finally: - mpl.interactive(was_interacive) + mpl.interactive(was_interactive) finally: mpl.rcParamsOrig["backend"] = orig_origbackend From dc2402d7b89d9e4ba08855da176c2ec07cef1de1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 5 Aug 2019 12:00:16 -0400 Subject: [PATCH 5/6] MNT: try using a simpler way of not messing with mpl state --- lib/matplotlib/backend_bases.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index a94846f6e24c..92dac12cfcaa 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1669,11 +1669,7 @@ def _fix_ipython_backend2gui(cls): if _is_non_interactive_terminal_ipython(ip): pass else: - was_interactive = mpl.is_interactive() - try: - ip.enable_matplotlib() - finally: - mpl.interactive(was_interactive) + ip.enable_gui() finally: mpl.rcParamsOrig["backend"] = orig_origbackend From bc65530323df308a8abe144a033eed26874d3930 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 5 Aug 2019 12:14:30 -0400 Subject: [PATCH 6/6] MNT: simplify and be explicit about what GUI to setup --- lib/matplotlib/backend_bases.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 92dac12cfcaa..9aad6a843e71 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1659,20 +1659,8 @@ def _fix_ipython_backend2gui(cls): backend2gui_rif = {"qt5": "qt", "qt4": "qt", "gtk3": "gtk3", "wx": "wx", "macosx": "osx"}.get(rif) if backend2gui_rif: - pt.backend2gui[get_backend()] = backend2gui_rif - # Work around pylabtools.find_gui_and_backend always reading from - # rcParamsOrig. - orig_origbackend = mpl.rcParamsOrig["backend"] - - try: - mpl.rcParamsOrig["backend"] = mpl.rcParams["backend"] - if _is_non_interactive_terminal_ipython(ip): - pass - else: - ip.enable_gui() - - finally: - mpl.rcParamsOrig["backend"] = orig_origbackend + if _is_non_interactive_terminal_ipython(ip): + ip.enable_gui(backend2gui_rif) @contextmanager def _idle_draw_cntx(self):