Skip to content

Commit

Permalink
Convert "osx" gui framework to/from "macosx" in Matplotlib (#14420)
Browse files Browse the repository at this point in the history
This is a correction to the code that moves backend handling to
Matplotlib, which came to light during the review of
matplotlib/matplotlib#27948. The GUI framework of macOSX is called `osx`
in IPython but `macosx` in Matplotlib.

It would be possible to allow passing a GUI framework of `osx` to
Matplotlib and internally converting it to `macosx`, but the reverse
direction is problematic as we would like the answer to be `osx` if we
are using IPython and `macosx` if using pure Matplotlib. Therefore the
simplest solution is to do the translation in IPython. It is not ideal
as we want to minimise such Matplotlib-related implementation details in
IPython, but the changes here are small and simple and hence I think
they are acceptable.

There are two new private functions `_convert_gui_to_matplotlib` and
`_convert_gui_from_matplotlib` to do the required checking and
conversion, and these are called whenever a GUI framework name is passed
to or from Matplotlib. There are only 3 places in the code where this is
currently required.

Inevitably this comes to light just after the release of IPython 8.24.0!
But it is not a problem for end users until the next Matplotlib release
which contains matplotlib/matplotlib#27948. If that occurs really
quickly (sometime in May?) perhaps we could release an IPython 8.24.1
just beforehand, otherwise the usual planned release at the end of next
month would be fine.
  • Loading branch information
Carreau committed May 6, 2024
2 parents f9982db + e63f26e commit 85bb530
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
22 changes: 21 additions & 1 deletion IPython/core/pylabtools.py
Expand Up @@ -345,8 +345,10 @@ def find_gui_and_backend(gui=None, gui_select=None):
backend = matplotlib.rcParamsOrig["backend"]
backend, gui = backend_registry.resolve_backend(backend)
else:
gui = _convert_gui_to_matplotlib(gui)
backend, gui = backend_registry.resolve_gui_or_backend(gui)

gui = _convert_gui_from_matplotlib(gui)
return gui, backend

# Fallback to previous behaviour (Matplotlib < 3.9)
Expand Down Expand Up @@ -509,10 +511,28 @@ def _list_matplotlib_backends_and_gui_loops() -> list[str]:
if _matplotlib_manages_backends():
from matplotlib.backends.registry import backend_registry

ret = backend_registry.list_all() + backend_registry.list_gui_frameworks()
ret = backend_registry.list_all() + [
_convert_gui_from_matplotlib(gui)
for gui in backend_registry.list_gui_frameworks()
]
else:
from IPython.core import pylabtools

ret = list(pylabtools.backends.keys())

return sorted(["auto"] + ret)


# Matplotlib and IPython do not always use the same gui framework name.
# Always use the approprate one of these conversion functions when passing a
# gui framework name to/from Matplotlib.
def _convert_gui_to_matplotlib(gui: str | None) -> str | None:
if gui and gui.lower() == "osx":
return "macosx"
return gui


def _convert_gui_from_matplotlib(gui: str | None) -> str | None:
if gui and gui.lower() == "macosx":
return "osx"
return gui
6 changes: 2 additions & 4 deletions IPython/core/tests/test_pylabtools.py
Expand Up @@ -276,11 +276,11 @@ def test_figure_no_canvas():
# name is gui
("gtk3", "gtk3", "gtk3agg"),
("gtk4", "gtk4", "gtk4agg"),
("headless", "headless", "agg"),
("headless", None, "agg"),
("osx", "osx", "macosx"),
("qt", "qt", "qtagg"),
("qt5", "qt5", "qt5agg"),
("qt6", "qt6", "qt6agg"),
("qt6", "qt6", "qtagg"),
("tk", "tk", "tkagg"),
("wx", "wx", "wxagg"),
# name is backend
Expand All @@ -301,8 +301,6 @@ def test_figure_no_canvas():
("qtcairo", "qt", "qtcairo"),
("qt5agg", "qt5", "qt5agg"),
("qt5cairo", "qt5", "qt5cairo"),
("qt6agg", "qt", "qt6agg"),
("qt6cairo", "qt", "qt6cairo"),
("tkagg", "tk", "tkagg"),
("tkcairo", "tk", "tkcairo"),
("webagg", "webagg", "webagg"),
Expand Down

0 comments on commit 85bb530

Please sign in to comment.