|
41 | 41 | from contextlib import contextmanager
|
42 | 42 | from functools import partial
|
43 | 43 | import importlib
|
| 44 | +import inspect |
44 | 45 | import io
|
45 | 46 | import os
|
46 | 47 | import sys
|
47 | 48 | import time
|
48 | 49 | import warnings
|
49 | 50 |
|
50 | 51 | import numpy as np
|
| 52 | +import matplotlib |
51 | 53 | import matplotlib.cbook as cbook
|
52 | 54 | import matplotlib.colors as colors
|
53 | 55 | import matplotlib.transforms as transforms
|
@@ -135,120 +137,6 @@ def get_registered_canvas_class(format):
|
135 | 137 | return backend_class
|
136 | 138 |
|
137 | 139 |
|
138 |
| -class _Backend(object): |
139 |
| - # A backend can be defined by using the following pattern: |
140 |
| - # |
141 |
| - # @_Backend.export |
142 |
| - # class FooBackend(_Backend): |
143 |
| - # # override the attributes and methods documented below. |
144 |
| - |
145 |
| - # The following attributes and methods must be overridden by subclasses. |
146 |
| - |
147 |
| - # The `FigureCanvas` and `FigureManager` classes must be defined. |
148 |
| - FigureCanvas = None |
149 |
| - FigureManager = None |
150 |
| - |
151 |
| - # The following methods must be left as None for non-interactive backends. |
152 |
| - # For interactive backends, `trigger_manager_draw` should be a function |
153 |
| - # taking a manager as argument and triggering a canvas draw, and `mainloop` |
154 |
| - # should be a function taking no argument and starting the backend main |
155 |
| - # loop. |
156 |
| - trigger_manager_draw = None |
157 |
| - mainloop = None |
158 |
| - |
159 |
| - # The following methods will be automatically defined and exported, but |
160 |
| - # can be overridden. |
161 |
| - |
162 |
| - @classmethod |
163 |
| - def new_figure_manager(cls, num, *args, **kwargs): |
164 |
| - """Create a new figure manager instance. |
165 |
| - """ |
166 |
| - # This import needs to happen here due to circular imports. |
167 |
| - from matplotlib.figure import Figure |
168 |
| - fig_cls = kwargs.pop('FigureClass', Figure) |
169 |
| - fig = fig_cls(*args, **kwargs) |
170 |
| - return cls.new_figure_manager_given_figure(num, fig) |
171 |
| - |
172 |
| - @classmethod |
173 |
| - def new_figure_manager_given_figure(cls, num, figure): |
174 |
| - """Create a new figure manager instance for the given figure. |
175 |
| - """ |
176 |
| - canvas = cls.FigureCanvas(figure) |
177 |
| - manager = cls.FigureManager(canvas, num) |
178 |
| - return manager |
179 |
| - |
180 |
| - @classmethod |
181 |
| - def draw_if_interactive(cls): |
182 |
| - if cls.trigger_manager_draw is not None and is_interactive(): |
183 |
| - manager = Gcf.get_active() |
184 |
| - if manager: |
185 |
| - cls.trigger_manager_draw(manager) |
186 |
| - |
187 |
| - @classmethod |
188 |
| - def show(cls, block=None): |
189 |
| - """Show all figures. |
190 |
| -
|
191 |
| - `show` blocks by calling `mainloop` if *block* is ``True``, or if it |
192 |
| - is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in |
193 |
| - `interactive` mode. |
194 |
| - """ |
195 |
| - if cls.mainloop is None: |
196 |
| - return |
197 |
| - managers = Gcf.get_all_fig_managers() |
198 |
| - if not managers: |
199 |
| - return |
200 |
| - for manager in managers: |
201 |
| - manager.show() |
202 |
| - if block is None: |
203 |
| - # Hack: Are we in IPython's pylab mode? |
204 |
| - from matplotlib import pyplot |
205 |
| - try: |
206 |
| - # IPython versions >= 0.10 tack the _needmain attribute onto |
207 |
| - # pyplot.show, and always set it to False, when in %pylab mode. |
208 |
| - ipython_pylab = not pyplot.show._needmain |
209 |
| - except AttributeError: |
210 |
| - ipython_pylab = False |
211 |
| - block = not ipython_pylab and not is_interactive() |
212 |
| - # TODO: The above is a hack to get the WebAgg backend working with |
213 |
| - # ipython's `%pylab` mode until proper integration is implemented. |
214 |
| - if get_backend() == "WebAgg": |
215 |
| - block = True |
216 |
| - if block: |
217 |
| - cls.mainloop() |
218 |
| - |
219 |
| - # This method is the one actually exporting the required methods. |
220 |
| - |
221 |
| - @staticmethod |
222 |
| - def export(cls): |
223 |
| - for name in ["FigureCanvas", |
224 |
| - "FigureManager", |
225 |
| - "new_figure_manager", |
226 |
| - "new_figure_manager_given_figure", |
227 |
| - "draw_if_interactive", |
228 |
| - "show"]: |
229 |
| - setattr(sys.modules[cls.__module__], name, getattr(cls, name)) |
230 |
| - |
231 |
| - # For back-compatibility, generate a shim `Show` class. |
232 |
| - |
233 |
| - class Show(ShowBase): |
234 |
| - def mainloop(self): |
235 |
| - return cls.mainloop() |
236 |
| - |
237 |
| - setattr(sys.modules[cls.__module__], "Show", Show) |
238 |
| - return cls |
239 |
| - |
240 |
| - |
241 |
| -class ShowBase(_Backend): |
242 |
| - """ |
243 |
| - Simple base class to generate a show() callable in backends. |
244 |
| -
|
245 |
| - Subclass must override mainloop() method. |
246 |
| - """ |
247 |
| - |
248 |
| - def __call__(self, block=None): |
249 |
| - return self.show(block=block) |
250 |
| - |
251 |
| - |
252 | 140 | class RendererBase(object):
|
253 | 141 | """An abstract base class to handle drawing/rendering operations.
|
254 | 142 |
|
@@ -3367,3 +3255,129 @@ def set_message(self, s):
|
3367 | 3255 | Message text
|
3368 | 3256 | """
|
3369 | 3257 | pass
|
| 3258 | + |
| 3259 | + |
| 3260 | +class _Backend(object): |
| 3261 | + # A backend can be defined by using the following pattern: |
| 3262 | + # |
| 3263 | + # @_Backend.export |
| 3264 | + # class FooBackend(_Backend): |
| 3265 | + # # override the attributes and methods documented below. |
| 3266 | + |
| 3267 | + # May be overridden by the subclass. |
| 3268 | + backend_version = "unknown" |
| 3269 | + # The `FigureCanvas` class must be overridden. |
| 3270 | + FigureCanvas = None |
| 3271 | + # For interactive backends, the `FigureManager` class must be overridden. |
| 3272 | + FigureManager = FigureManagerBase |
| 3273 | + # The following methods must be left as None for non-interactive backends. |
| 3274 | + # For interactive backends, `trigger_manager_draw` should be a function |
| 3275 | + # taking a manager as argument and triggering a canvas draw, and `mainloop` |
| 3276 | + # should be a function taking no argument and starting the backend main |
| 3277 | + # loop. |
| 3278 | + trigger_manager_draw = None |
| 3279 | + mainloop = None |
| 3280 | + |
| 3281 | + # The following methods will be automatically defined and exported, but |
| 3282 | + # can be overridden. |
| 3283 | + |
| 3284 | + @classmethod |
| 3285 | + def new_figure_manager(cls, num, *args, **kwargs): |
| 3286 | + """Create a new figure manager instance. |
| 3287 | + """ |
| 3288 | + # This import needs to happen here due to circular imports. |
| 3289 | + from matplotlib.figure import Figure |
| 3290 | + fig_cls = kwargs.pop('FigureClass', Figure) |
| 3291 | + fig = fig_cls(*args, **kwargs) |
| 3292 | + return cls.new_figure_manager_given_figure(num, fig) |
| 3293 | + |
| 3294 | + @classmethod |
| 3295 | + def new_figure_manager_given_figure(cls, num, figure): |
| 3296 | + """Create a new figure manager instance for the given figure. |
| 3297 | + """ |
| 3298 | + canvas = cls.FigureCanvas(figure) |
| 3299 | + manager = cls.FigureManager(canvas, num) |
| 3300 | + return manager |
| 3301 | + |
| 3302 | + @classmethod |
| 3303 | + def draw_if_interactive(cls): |
| 3304 | + if cls.trigger_manager_draw is not None and is_interactive(): |
| 3305 | + manager = Gcf.get_active() |
| 3306 | + if manager: |
| 3307 | + cls.trigger_manager_draw(manager) |
| 3308 | + |
| 3309 | + @classmethod |
| 3310 | + def show(cls, block=None): |
| 3311 | + """Show all figures. |
| 3312 | +
|
| 3313 | + `show` blocks by calling `mainloop` if *block* is ``True``, or if it |
| 3314 | + is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in |
| 3315 | + `interactive` mode. |
| 3316 | + """ |
| 3317 | + if cls.mainloop is None: |
| 3318 | + frame = inspect.currentframe() |
| 3319 | + while frame: |
| 3320 | + if frame.f_code.co_filename in [ |
| 3321 | + "<stdin>", "<ipython console>"]: |
| 3322 | + warnings.warn("""\ |
| 3323 | +Your currently selected backend does not support show(). |
| 3324 | +Please select a GUI backend in your matplotlibrc file ('{}') |
| 3325 | +or with matplotlib.use()""".format(matplotlib.matplotlib_fname())) |
| 3326 | + break |
| 3327 | + else: |
| 3328 | + frame = frame.f_back |
| 3329 | + return |
| 3330 | + managers = Gcf.get_all_fig_managers() |
| 3331 | + if not managers: |
| 3332 | + return |
| 3333 | + for manager in managers: |
| 3334 | + manager.show() |
| 3335 | + if block is None: |
| 3336 | + # Hack: Are we in IPython's pylab mode? |
| 3337 | + from matplotlib import pyplot |
| 3338 | + try: |
| 3339 | + # IPython versions >= 0.10 tack the _needmain attribute onto |
| 3340 | + # pyplot.show, and always set it to False, when in %pylab mode. |
| 3341 | + ipython_pylab = not pyplot.show._needmain |
| 3342 | + except AttributeError: |
| 3343 | + ipython_pylab = False |
| 3344 | + block = not ipython_pylab and not is_interactive() |
| 3345 | + # TODO: The above is a hack to get the WebAgg backend working with |
| 3346 | + # ipython's `%pylab` mode until proper integration is implemented. |
| 3347 | + if get_backend() == "WebAgg": |
| 3348 | + block = True |
| 3349 | + if block: |
| 3350 | + cls.mainloop() |
| 3351 | + |
| 3352 | + # This method is the one actually exporting the required methods. |
| 3353 | + |
| 3354 | + @staticmethod |
| 3355 | + def export(cls): |
| 3356 | + for name in ["backend_version", |
| 3357 | + "FigureCanvas", |
| 3358 | + "FigureManager", |
| 3359 | + "new_figure_manager", |
| 3360 | + "new_figure_manager_given_figure", |
| 3361 | + "draw_if_interactive", |
| 3362 | + "show"]: |
| 3363 | + setattr(sys.modules[cls.__module__], name, getattr(cls, name)) |
| 3364 | + |
| 3365 | + # For back-compatibility, generate a shim `Show` class. |
| 3366 | + |
| 3367 | + class Show(ShowBase): |
| 3368 | + def mainloop(self): |
| 3369 | + return cls.mainloop() |
| 3370 | + |
| 3371 | + setattr(sys.modules[cls.__module__], "Show", Show) |
| 3372 | + return cls |
| 3373 | + |
| 3374 | + |
| 3375 | +class ShowBase(_Backend): |
| 3376 | + """ |
| 3377 | + Simple base class to generate a show() callable in backends. |
| 3378 | +
|
| 3379 | + Subclass must override mainloop() method. |
| 3380 | + """ |
| 3381 | + |
| 3382 | + def __call__(self, block=None): |
| 3383 | + return self.show(block=block) |
0 commit comments