Skip to content

replace BACKEND_SPECS with matplotlib.backends.backend_registry #5138

@chrishavlin

Description

@chrishavlin

While updating the BACKEND_SPECS in #5135 , I noticed that matplotlib 3.9 introduced a matplotlib.backends.backend_registry that could be used to replace BACKEND_SPECS entirely and offload the backend details to matplotlib.

e.g., could add the following to get the FigureCanvas and FigureManager classes in _get_canvas_classes

if matplotlib.__version_info__ >= (3, 9):
    from matplotlib.backends import backend_registry

    mod = backend_registry.load_backend_module(key)
    FigureCanvas = getattr(mod, 'FigureCanvas')
    FigureManager = getattr(mod, 'FigureManager')

Only thing I'm a little uncertain of is the FigureManager -- from what I understand, the above code pulls out FigureCanvas and FigureManager classes that are aliased to the specific implementation for each backend and there should always be a FigureManager specified (which seems to have been the case for quite a while now... since matplotlib/matplotlib#8773). Any reason to preserve yt's behavior for the backends where None is specified for a FigureManager in BACKEND_SPECS? I think no, but wanted to get a second opinion.

here's the relevant bits of code i'm referring to:

BACKEND_SPECS = {
"GTK": ["backend_gtk", "FigureCanvasGTK", "FigureManagerGTK"],
"GTKAgg": ["backend_gtkagg", "FigureCanvasGTKAgg", None],
"GTKCairo": ["backend_gtkcairo", "FigureCanvasGTKCairo", None],
"MacOSX": ["backend_macosx", "FigureCanvasMac", "FigureManagerMac"],
"Qt5Agg": ["backend_qt5agg", "FigureCanvasQTAgg", None],
"QtAgg": ["backend_qtagg", "FigureCanvasQTAgg", None],
"TkAgg": ["backend_tkagg", "FigureCanvasTkAgg", None],
"WX": ["backend_wx", "FigureCanvasWx", None],
"WXAgg": ["backend_wxagg", "FigureCanvasWxAgg", None],
"GTK3Cairo": [
"backend_gtk3cairo",
"FigureCanvasGTK3Cairo",
"FigureManagerGTK3Cairo",
],
"GTK3Agg": ["backend_gtk3agg", "FigureCanvasGTK3Agg", "FigureManagerGTK3Agg"],
"WebAgg": ["backend_webagg", "FigureCanvasWebAgg", None],
"nbAgg": ["backend_nbagg", "FigureCanvasNbAgg", "FigureManagerNbAgg"],
"agg": ["backend_agg", "FigureCanvasAgg", None],
}

and

def _get_canvas_classes(self):
if self.interactivity:
key = str(matplotlib.get_backend())
else:
key = "agg"
module, fig_canvas, fig_manager = BACKEND_SPECS[key]
mod = __import__(
"matplotlib.backends",
globals(),
locals(),
[module],
0,
)
submod = getattr(mod, module)
FigureCanvas = getattr(submod, fig_canvas)
if fig_manager is not None:
FigureManager = getattr(submod, fig_manager)
return FigureCanvas, FigureManager
return FigureCanvas, None

Also, I don't see a huge benefit to putting this change in now vs waiting til yt's min matplotlib version is 3.9, but wanted to get these thoughts down while they're fresh.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionrefactorimprove readability, maintainability, modularityviz: 2D

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions