8000 Merge pull request #23090 from anntzer/nfm · matplotlib/matplotlib@8e34e70 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8e34e70

8000 Browse files
authored
Merge pull request #23090 from anntzer/nfm
Derive new_figure_manager from FigureCanvas.new_manager.
2 parents 7fba039 + d018786 commit 8e34e70

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

lib/matplotlib/pyplot.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,9 @@ def switch_backend(newbackend):
266266
rcParamsOrig["backend"] = "agg"
267267
return
268268

269-
# Backends are implemented as modules, but "inherit" default method
270-
# implementations from backend_bases._Backend. This is achieved by
271-
# creating a "class" that inherits from backend_bases._Backend and whose
272-
# body is filled with the module's globals.
273-
274-
backend_name = cbook._backend_module_name(newbackend)
275-
276-
class backend_mod(matplotlib.backend_bases._Backend):
277-
locals().update(vars(importlib.import_module(backend_name)))
269+
backend_mod = importlib.import_module(
270+
cbook._backend_module_name(newbackend))
271+
canvas_class = backend_mod.FigureCanvas
278272

279273
required_framework = _get_required_interactive_framework(backend_mod)
280274
if required_framework is not None:
@@ -286,6 +280,36 @@ class backend_mod(matplotlib.backend_bases._Backend):
286280
"framework, as {!r} is currently running".format(
287281
newbackend, required_framework, current_framework))
288282

283+
# Load the new_figure_manager(), draw_if_interactive(), and show()
284+
# functions from the backend.
285+
286+
# Classically, backends can directly export these functions. This should
287+
# keep working for backcompat.
288+
new_figure_manager = getattr(backend_mod, "new_figure_manager", None)
289+
# draw_if_interactive = getattr(backend_mod, "draw_if_interactive", None)
290+
# show = getattr(backend_mod, "show", None)
291+
# In that classical approach, backends are implemented as modules, but
292+
# "inherit" default method implementations from backend_bases._Backend.
293+
# This is achieved by creating a "class" that inherits from
294+
# backend_bases._Backend and whose body is filled with the module globals.
295+
class backend_mod(matplotlib.backend_bases._Backend):
296+
locals().update(vars(backend_mod))
297+
298+
# However, the newer approach for defining new_figure_manager (and, in
299+
# the future, draw_if_interactive and show) is to derive them from canvas
300+
# methods. In that case, also update backend_mod accordingly.
301+
if new_figure_manager is None:
302+
def new_figure_manager_given_figure(num, figure):
303+
return canvas_class.new_manager(figure, num)
304+
305+
def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
306+
fig = FigureClass(*args, **kwargs)
307+
return new_figure_manager_given_figure(num, fig)
308+
309+
backend_mod.new_figure_manager_given_figure = \
310+
new_figure_manager_given_figure
311+
backend_mod.new_figure_manager = new_figure_manager
312+
289313
_log.debug("Loaded backend %s version %s.",
290314
newbackend, backend_mod.backend_version)
291315

lib/matplotlib/testing/conftest.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ def mpl_test_settings(request):
4444

4545
backend = None
4646
backend_marker = request.node.get_closest_marker('backend')
47+
prev_backend = matplotlib.get_backend()
4748
if backend_marker is not None:
4849
assert len(backend_marker.args) == 1, \
4950
"Marker 'backend' must specify 1 backend."
5051
backend, = backend_marker.args
5152
skip_on_importerror = backend_marker.kwargs.get(
5253
'skip_on_importerror', False)
53-
prev_backend = matplotlib.get_backend()
5454

5555
# special case Qt backend importing to avoid conflicts
5656
if backend.lower().startswith('qt5'):
@@ -87,8 +87,7 @@ def mpl_test_settings(request):
8787
try:
8888
yield
8989
finally:
90-
if backend is not None:
91-
plt.switch_backend(prev_backend)
90+
matplotlib.use(prev_backend)
9291

9392

9493
@pytest.fixture
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
Backend-loading machinery tests, using variations on the template backend.
3+
"""
4+
5+
import sys
6+
from types import SimpleNamespace
7+
8+
import matplotlib as mpl
9+
from matplotlib import pyplot as plt
10+
from matplotlib.backends import backend_template
11+
12+
13+
def test_load_template():
14+
mpl.use("template")
15+
assert type(plt.figure().canvas) == backend_template.FigureCanvasTemplate
16+
17+
18+
def test_new_manager(monkeypatch):
19+
mpl_test_backend = SimpleNamespace(**vars(backend_template))
20+
del mpl_test_backend.new_figure_manager
21+
monkeypatch.setitem(sys.modules, "mpl_test_backend", mpl_test_backend)
22+
mpl.use("module://mpl_test_backend")
23+
assert type(plt.figure().canvas) == backend_template.FigureCanvasTemplate

0 commit comments

Comments
 (0)
0