Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9bd7184

Browse files
committed
Derive new_figure_manager from FigureCanvas.new_manager.
Followup to the introduction of FigureCanvas.new_manager: allow backend modules to not define new_figure_manager anymore, in which case we derive the needed function from FigureCanvas.new_manager. (In the future, I plan to do the same with draw_if_interactive and show, so that "a backend is just a module with a FigureCanvas class"; the advantage is that the FigureCanvas subclass provided by the module can inherit methods as needed from the parent class.) For backcompat, the old codepath is maintained (and has priority). To test this, manually alter backend_bases._Backend.export and remove the new_figure_manager entry from the exported functions, which deletes that global function from all of the builtin methods (actually, we'll need a deprecation cycle), and check that pyplot still works fine.
1 parent 037fcca commit 9bd7184

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
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

0 commit comments

Comments
 (0)