Skip to content

In the new/simplified backend API, don't customize draw_if_interactive. #23291

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 1 commit into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions doc/api/next_api_changes/removals/23291-AL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``backend_template.new_figure_manager``, ``backend_template.new_figure_manager_given_figure``, and ``backend_template.draw_if_interactive``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... have been removed, as part of the introduction of the simplified backend
API.
29 changes: 3 additions & 26 deletions lib/matplotlib/backends/backend_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,6 @@ class GraphicsContextTemplate(GraphicsContextBase):
########################################################################


def draw_if_interactive():
"""
For image backends - is not required.
For GUI backends - this should be overridden if drawing should be done in
interactive python mode.
"""


def show(*, block=None):
"""
For image backends - is not required.
Expand All @@ -156,24 +148,6 @@ def show(*, block=None):
pass


def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
"""Create a new figure manager instance."""
thisFig = FigureClass(*args, **kwargs)
return new_figure_manager_given_figure(num, thisFig)


def new_figure_manager_given_figure(num, figure):
"""Create a new figure manager instance for the given figure."""
# If a main-level app must be created, this is the usual place to do it
# -- see the wx and tk backends for examples (the default implementation
# of new_figure_manager defers to new_figure_manager_given_figure, so it
# also benefits from this instantiation). Not all GUIs require explicit
# instantiation of a main-level app (e.g., backend_gtk3) for pylab.
canvas = FigureCanvasTemplate(figure)
manager = FigureManagerTemplate(canvas, num)
return manager


class FigureManagerTemplate(FigureManagerBase):
"""
Helper class for pyplot mode, wraps everything up into a neat bundle.
Expand All @@ -199,6 +173,9 @@ class methods button_press_event, button_release_event,
A high-level Figure instance
"""

# The instantiated manager class. For further customization,
# ``FigureManager.create_with_canvas`` can also be overridden; see the
# wx-based backends for an example.
manager_class = FigureManagerTemplate

def draw(self):
Expand Down
22 changes: 14 additions & 8 deletions lib/matplotlib/pyplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,11 @@ def switch_backend(newbackend):
"framework, as {!r} is currently running".format(
newbackend, required_framework, current_framework))

# Load the new_figure_manager(), draw_if_interactive(), and show()
# functions from the backend.
# Load the new_figure_manager() and show() functions from the backend.

# Classically, backends can directly export these functions. This should
# keep working for backcompat.
new_figure_manager = getattr(backend_mod, "new_figure_manager", None)
# draw_if_interactive = getattr(backend_mod, "draw_if_interactive", None)
# show = getattr(backend_mod, "show", None)
# In that classical approach, backends are implemented as modules, but
# "inherit" default method implementations from backend_bases._Backend.
Expand All @@ -290,8 +288,9 @@ class backend_mod(matplotlib.backend_bases._Backend):
locals().update(vars(backend_mod))

# However, the newer approach for defining new_figure_manager (and, in
# the future, draw_if_interactive and show) is to derive them from canvas
# methods. In that case, also update backend_mod accordingly.
# the future, show) is to derive them from canvas methods. In that case,
# also update backend_mod accordingly; also, per-backend customization of
# draw_if_interactive is disabled.
if new_figure_manager is None:
def new_figure_manager_given_figure(num, figure):
return canvas_class.new_manager(figure, num)
Expand All @@ -300,9 +299,16 @@ def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
fig = FigureClass(*args, **kwargs)
return new_figure_manager_given_figure(num, fig)

def draw_if_interactive():
if matplotlib.is_interactive():
manager = _pylab_helpers.Gcf.get_active()
if manager:
manager.canvas.draw_idle()

backend_mod.new_figure_manager_given_figure = \
new_figure_manager_given_figure
backend_mod.new_figure_manager = new_figure_manager
backend_mod.draw_if_interactive = draw_if_interactive

_log.debug("Loaded backend %s version %s.",
newbackend, backend_mod.backend_version)
Expand Down Expand Up @@ -762,9 +768,9 @@ def figure(num=None, # autoincrement if None, else integer from 1-N

Notes
-----
Newly created figures will be passed to the
`~.backend_template.new_figure_manager` function provided by the current
backend, which will install a canvas and a manager on the figure.
Newly created figures are passed to the `~.FigureCanvasBase.new_manager`
method or the `new_figure_manager` function provided by the current
backend, which install a canvas and a manager on the figure.

If you are creating many figures, make sure you explicitly call
`.pyplot.close` on the figures you are not using, because this will
Expand Down
14 changes: 10 additions & 4 deletions lib/matplotlib/tests/test_backend_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib.backends import backend_template
from matplotlib.backends.backend_template import (
FigureCanvasTemplate, FigureManagerTemplate)


def test_load_template():
mpl.use("template")
assert type(plt.figure().canvas) == backend_template.FigureCanvasTemplate
assert type(plt.figure().canvas) == FigureCanvasTemplate


def test_new_manager(monkeypatch):
def test_load_old_api(monkeypatch):
mpl_test_backend = SimpleNamespace(**vars(backend_template))
del mpl_test_backend.new_figure_manager
mpl_test_backend.new_figure_manager = (
lambda num, *args, FigureClass=mpl.figure.Figure, **kwargs:
FigureManagerTemplate(
FigureCanvasTemplate(FigureClass(*args, **kwargs)), num))
monkeypatch.setitem(sys.modules, "mpl_test_backend", mpl_test_backend)
mpl.use("module://mpl_test_backend")
assert type(plt.figure().canvas) == backend_template.FigureCanvasTemplate
assert type(plt.figure().canvas) == FigureCanvasTemplate
plt.draw_if_interactive()