Skip to content

Tell IPython the correct GUI event loop to use for all backends. #12637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 13, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

from contextlib import contextmanager
from enum import IntEnum
import functools
import importlib
import io
import logging
Expand All @@ -44,6 +45,7 @@

import numpy as np

import matplotlib as mpl
from matplotlib import (
backend_tools as tools, cbook, colors, textpath, tight_bbox, transforms,
widgets, get_backend, is_interactive, rcParams)
Expand Down Expand Up @@ -1564,6 +1566,7 @@ class FigureCanvasBase(object):
'Tagged Image File Format')

def __init__(self, figure):
self._fix_ipython_backend2gui()
self._is_idle_drawing = True
self._is_saving = False
figure.set_canvas(self)
Expand All @@ -1580,6 +1583,40 @@ def __init__(self, figure):
self.toolbar = None # NavigationToolbar2 will set me
self._is_idle_drawing = False

@classmethod
@functools.lru_cache()
def _fix_ipython_backend2gui(cls):
# Fix hard-coded module -> toolkit mapping in IPython (used for
# `ipython --auto`). This cannot be done at import time due to
# ordering issues, so we do it when creating a canvas, and should only
# be done once per class (hence the `lru_cache(1)`).
if "IPython" not in sys.modules:
return
import IPython
ip = IPython.get_ipython()
if not ip:
return
from IPython.core import pylabtools as pt
if (not hasattr(pt, "backend2gui")
or not hasattr(ip, "enable_matplotlib")):
# In case we ever move the patch to IPython and remove these APIs,
# don't break on our side.
return
backend_mod = sys.modules[cls.__module__]
rif = getattr(backend_mod, "required_interactive_framework", None)
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"]
ip.enable_matplotlib()
finally:
mpl.rcParamsOrig["backend"] = orig_origbackend

@contextmanager
def _idle_draw_cntx(self):
self._is_idle_drawing = True
Expand Down