Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7b8b41b

Browse filesBrowse files
committed
Revival of the backend loading refactor.
1 parent 6cf8450 commit 7b8b41b
Copy full SHA for 7b8b41b

File tree

Expand file treeCollapse file tree

6 files changed

+145
-166
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+145
-166
lines changed
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Non-interactive FigureManager classes are now aliases of FigureManagerBase
2+
``````````````````````````````````````````````````````````````````````````
3+
4+
The `FigureManagerPdf`, `FigureManagerPS`, and `FigureManagerSVG` classes,
5+
which were previously empty subclasses of `FigureManagerBase` (i.e., not
6+
adding or overriding any attribute or method), are now direct aliases for
7+
`FigureManagerBase`.

‎lib/matplotlib/backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_bases.py
+119-115Lines changed: 119 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -124,121 +124,6 @@ def get_registered_canvas_class(format):
124124
return backend_class
125125

126126

127-
class _Backend(object):
128-
# A backend can be defined by using the following pattern:
129-
#
130-
# @_Backend.export
131-
# class FooBackend(_Backend):
132-
# # override the attributes and methods documented below.
133-
134-
# The following attributes and methods must be overridden by subclasses.
135-
136-
# The `FigureCanvas` and `FigureManager` classes must be defined.
137-
FigureCanvas = None
138-
FigureManager = None
139-
140-
# The following methods must be left as None for non-interactive backends.
141-
# For interactive backends, `trigger_manager_draw` should be a function
142-
# taking a manager as argument and triggering a canvas draw, and `mainloop`
143-
# should be a function taking no argument and starting the backend main
144-
# loop.
145-
trigger_manager_draw = None
146-
mainloop = None
147-
148-
# The following methods will be automatically defined and exported, but
149-
# can be overridden.
150-
151-
@classmethod
152-
def new_figure_manager(cls, num, *args, **kwargs):
153-
"""Create a new figure manager instance.
154-
"""
155-
# This import needs to happen here due to circular imports.
156-
from matplotlib.figure import Figure
157-
fig_cls = kwargs.pop('FigureClass', Figure)
158-
fig = fig_cls(*args, **kwargs)
159-
return cls.new_figure_manager_given_figure(num, fig)
160-
161-
@classmethod
162-
def new_figure_manager_given_figure(cls, num, figure):
163-
"""Create a new figure manager instance for the given figure.
164-
"""
165-
canvas = cls.FigureCanvas(figure)
166-
manager = cls.FigureManager(canvas, num)
167-
return manager
168-
169-
@classmethod
170-
def draw_if_interactive(cls):
171-
if cls.trigger_manager_draw is not None and is_interactive():
172-
manager = Gcf.get_active()
173-
if manager:
174-
cls.trigger_manager_draw(manager)
175-
176-
@classmethod
177-
def show(cls, block=None):
178-
"""Show all figures.
179-
180-
`show` blocks by calling `mainloop` if *block* is ``True``, or if it
181-
is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in
182-
`interactive` mode.
183-
"""
184-
managers = Gcf.get_all_fig_managers()
185-
if not managers:
186-
return
187-
for manager in managers:
188-
# Emits a warning if the backend is non-interactive.
189-
manager.canvas.figure.show()
190-
if cls.mainloop is None:
191-
return
192-
if block is None:
193-
# Hack: Are we in IPython's pylab mode?
194-
from matplotlib import pyplot
195-
try:
196-
# IPython versions >= 0.10 tack the _needmain attribute onto
197-
# pyplot.show, and always set it to False, when in %pylab mode.
198-
ipython_pylab = not pyplot.show._needmain
199-
except AttributeError:
200-
ipython_pylab = False
201-
block = not ipython_pylab and not is_interactive()
202-
# TODO: The above is a hack to get the WebAgg backend working with
203-
# ipython's `%pylab` mode until proper integration is implemented.
204-
if get_backend() == "WebAgg":
205-
block = True
206-
if block:
207-
cls.mainloop()
208-
209-
# This method is the one actually exporting the required methods.
210-
211-
@staticmethod
212-
def export(cls):
213-
for name in ["FigureCanvas",
214-
"FigureManager",
215-
"new_figure_manager",
216-
"new_figure_manager_given_figure",
217-
"draw_if_interactive",
218-
"show"]:
219-
setattr(sys.modules[cls.__module__], name, getattr(cls, name))
220-
221-
# For back-compatibility, generate a shim `Show` class.
222-
223-
class Show(ShowBase):
224-
def mainloop(self):
225-
return cls.mainloop()
226-
227-
setattr(sys.modules[cls.__module__], "Show", Show)
228-
return cls
229-
230-
231-
class ShowBase(_Backend):
232-
"""
233-
Simple base class to generate a show() callable in backends.
234-
235-
Subclass must override mainloop() method.
236-
"""
237-
238-
def __call__(self, block=None):
239-
return self.show(block=block)
240-
241-
242127
class RendererBase(object):
243128
"""An abstract base class to handle drawing/rendering operations.
244129
@@ -3328,3 +3213,122 @@ def set_message(self, s):
33283213
Message text
33293214
"""
33303215
pass
3216+
3217+
3218+
class _Backend(object):
3219+
# A backend can be defined by using the following pattern:
3220+
#
3221+
# @_Backend.export
3222+
# class FooBackend(_Backend):
3223+
# # override the attributes and methods documented below.
3224+
3225+
# `backend_version` may be overridden by the subclass.
3226+
backend_version = "unknown"
3227+
3228+
# The `FigureCanvas` class must be defined.
3229+
FigureCanvas = None
3230+
3231+
# For interactive backends, the `FigureManager` class must be overridden.
3232+
FigureManager = FigureManagerBase
3233+
3234+
# The following methods must be left as None for non-interactive backends.
3235+
# For interactive backends, `trigger_manager_draw` should be a function
3236+
# taking a manager as argument and triggering a canvas draw, and `mainloop`
3237+
# should be a function taking no argument and starting the backend main
3238+
# loop.
3239+
trigger_manager_draw = None
3240+
mainloop = None
3241+
3242+
# The following methods will be automatically defined and exported, but
3243+
# can be overridden.
3244+
3245+
@classmethod
3246+
def new_figure_manager(cls, num, *args, **kwargs):
3247+
"""Create a new figure manager instance.
3248+
"""
3249+
# This import needs to happen here due to circular imports.
3250+
from matplotlib.figure import Figure
3251+
fig_cls = kwargs.pop('FigureClass', Figure)
3252+
fig = fig_cls(*args, **kwargs)
3253+
return cls.new_figure_manager_given_figure(num, fig)
3254+
3255+
@classmethod
3256+
def new_figure_manager_given_figure(cls, num, figure):
3257+
"""Create a new figure manager instance for the given figure.
3258+
"""
3259+
canvas = cls.FigureCanvas(figure)
3260+
manager = cls.FigureManager(canvas, num)
3261+
return manager
3262+
3263+
@classmethod
3264+
def draw_if_interactive(cls):
3265+
if cls.trigger_manager_draw is not None and is_interactive():
3266+
manager = Gcf.get_active()
3267+
if manager:
3268+
cls.trigger_manager_draw(manager)
3269+
3270+
@classmethod
3271+
def show(cls, block=None):
3272+
"""Show all figures.
3273+
3274+
`show` blocks by calling `mainloop` if *block* is ``True``, or if it
3275+
is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in
3276+
`interactive` mode.
3277+
"""
3278+
managers = Gcf.get_all_fig_managers()
3279+
if not managers:
3280+
return
3281+
for manager in managers:
3282+
# Emits a warning if the backend is non-interactive.
3283+
manager.canvas.figure.show()
3284+
if cls.mainloop is None:
3285+
return
3286+
if block is None:
3287+
# Hack: Are we in IPython's pylab mode?
3288+
from matplotlib import pyplot
3289+
try:
3290+
# IPython versions >= 0.10 tack the _needmain attribute onto
3291+
# pyplot.show, and always set it to False, when in %pylab mode.
3292+
ipython_pylab = not pyplot.show._needmain
3293+
except AttributeError:
3294+
ipython_pylab = False
3295+
block = not ipython_pylab and not is_interactive()
3296+
# TODO: The above is a hack to get the WebAgg backend working with
3297+
# ipython's `%pylab` mode until proper integration is implemented.
3298+
if get_backend() == "WebAgg":
3299+
block = True
3300+
if block:
3301+
cls.mainloop()
3302+
3303+
# This method is the one actually exporting the required methods.
3304+
3305+
@staticmethod
3306+
def export(cls):
3307+
for name in ["backend_version",
3308+
"FigureCanvas",
3309+
"FigureManager",
3310+
"new_figure_manager",
3311+
"new_figure_manager_given_figure",
3312+
"draw_if_interactive",
3313+
"show"]:
3314+
setattr(sys.modules[cls.__module__], name, getattr(cls, name))
3315+
3316+
# For back-compatibility, generate a shim `Show` class.
3317+
3318+
class Show(ShowBase):
3319+
def mainloop(self):
3320+
return cls.mainloop()
3321+
3322+
setattr(sys.modules[cls.__module__], "Show", Show)
3323+
return cls
3324+
3325+
3326+
class ShowBase(_Backend):
3327+
"""
3328+
Simple base class to generate a show() callable in backends.
3329+
3330+
Subclass must override mainloop() method.
3331+
"""
3332+
3333+
def __call__(self, block=None):
3334+
return self.show(block=block)

‎lib/matplotlib/backends/__init__.py

Copy file name to clipboard
+15-42Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import importlib
12
import inspect
23
import logging
34
import traceback
4-
import warnings
55

66
import matplotlib
7+
from matplotlib.backend_bases import _Backend
78

89
_log = logging.getLogger(__name__)
910

@@ -43,50 +44,22 @@ def pylab_setup(name=None):
4344
'''
4445
# Import the requested backend into a generic module object
4546
if name is None:
46-
# validates, to match all_backends
4747
name = matplotlib.get_backend()
48-
if name.startswith('module://'):
49-
backend_name = name[9:]
50-
else:
51-
backend_name = 'backend_' + name
52-
backend_name = backend_name.lower() # until we banish mixed case
53-
backend_name = 'matplotlib.backends.%s' % backend_name.lower()
54-
55-
# the last argument is specifies whether to use absolute or relative
56-
# imports. 0 means only perform absolute imports.
57-
backend_mod = __import__(backend_name, globals(), locals(),
58-
[backend_name], 0)
59-
60-
# Things we pull in from all backends
61-
new_figure_manager = backend_mod.new_figure_manager
62-
63-
# image backends like pdf, agg or svg do not need to do anything
64-
# for "show" or "draw_if_interactive", so if they are not defined
65-
# by the backend, just do nothing
66-
def do_nothing_show(*args, **kwargs):
67-
frame = inspect.currentframe()
68-
fname = frame.f_back.f_code.co_filename
69-
if fname in ('<stdin>', '<ipython console>'):
70-
warnings.warn("""
71-
Your currently selected backend, '%s' does not support show().
72-
Please select a GUI backend in your matplotlibrc file ('%s')
73-
or with matplotlib.use()""" %
74-
(name, matplotlib.matplotlib_fname()))
75-
76-
def do_nothing(*args, **kwargs):
77-
pass
78-
79-
backend_version = getattr(backend_mod, 'backend_version', 'unknown')
80-
81-
show = getattr(backend_mod, 'show', do_nothing_show)
82-
83-
draw_if_interactive = getattr(backend_mod, 'draw_if_interactive',
84-
do_nothing)
85-
86-
_log.debug('backend %s version %s', name, backend_version)
48+
backend_name = (name[9:] if name.startswith("module://")
49+
else "matplotlib.backends.backend_{}".format(name.lower()))
50+
backend_mod = importlib.import_module(backend_name)
51+
# Create a local Backend class whose body corresponds to the contents of
52+
# the backend module. This allows the Backend class to fill in the missing
53+
# methods through inheritance.
54+
Backend = type("Backend", (_Backend,), vars(backend_mod))
8755

8856
# need to keep a global reference to the backend for compatibility
8957
# reasons. See https://github.com/matplotlib/matplotlib/issues/6092
9058
global backend
9159
backend = name
92-
return backend_mod, new_figure_manager, draw_if_interactive, show
60+
61+
_log.debug('backend %s version %s', name, Backend.backend_version)
62+
return (backend_mod,
63+
Backend.new_figure_manager,
64+
Backend.draw_if_interactive,
65+
Backend.show)

‎lib/matplotlib/backends/backend_pdf.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_pdf.py
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,11 +2582,9 @@ def print_pdf(self, filename, *,
25822582
file.close()
25832583

25842584

2585-
class FigureManagerPdf(FigureManagerBase):
2586-
pass
2585+
FigureManagerPdf = FigureManagerBase
25872586

25882587

25892588
@_Backend.export
25902589
class _BackendPdf(_Backend):
25912590
FigureCanvas = FigureCanvasPdf
2592-
FigureManager = FigureManagerPdf

‎lib/matplotlib/backends/backend_ps.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_ps.py
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,8 +1699,7 @@ def pstoeps(tmpfile, bbox=None, rotated=False):
16991699
shutil.move(epsfile, tmpfile)
17001700

17011701

1702-
class FigureManagerPS(FigureManagerBase):
1703-
pass
1702+
FigureManagerPS = FigureManagerBase
17041703

17051704

17061705
# The following Python dictionary psDefs contains the entries for the
@@ -1746,4 +1745,3 @@ class FigureManagerPS(FigureManagerBase):
17461745
@_Backend.export
17471746
class _BackendPS(_Backend):
17481747
FigureCanvas = FigureCanvasPS
1749-
FigureManager = FigureManagerPS

‎lib/matplotlib/backends/backend_svg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_svg.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,8 +1213,8 @@ def _print_svg(
12131213
def get_default_filetype(self):
12141214
return 'svg'
12151215

1216-
class FigureManagerSVG(FigureManagerBase):
1217-
pass
1216+
1217+
FigureManagerSVG = FigureManagerBase
12181218

12191219

12201220
svgProlog = """\
@@ -1228,4 +1228,3 @@ class FigureManagerSVG(FigureManagerBase):
12281228
@_Backend.export
12291229
class _BackendSVG(_Backend):
12301230
FigureCanvas = FigureCanvasSVG
1231-
FigureManager = FigureManagerSVG

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.