From 023f3c54c6f98fae5286a4b00bd7b364a9936ef0 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 17 Feb 2023 11:01:55 +0100 Subject: [PATCH] Avoid calling vars() on arbitrary third-party manager_class. vars(...) may fail if the third-party manager_class has no `__dict__`, which can happen in contrieved cases involving `__slots__` or extension modules, or more simply if the backend has no FigureCanvas attribute or if the canvas class has no manager_class attribute, in which case manager_class = None. (Note that this can only be the case if that third-party FigureCanvas doesn't inherit from FigureCanvasBase, which is probably not a great idea.) In any case, instead of vars(), inspect.getattr_static does what we want too and also handles that case. Also replace another (unrelated) use of vars() with a plain getattr. --- lib/matplotlib/backends/backend_qt.py | 2 +- lib/matplotlib/pyplot.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index d0779f017b80..8abc7db3b5fa 100644 --- a/lib/matplotlib/backends/backend_qt.py +++ b/lib/matplotlib/backends/backend_qt.py @@ -898,7 +898,7 @@ def _tight_layout(self): self._figure.tight_layout() for attr, spinbox in self._spinboxes.items(): spinbox.blockSignals(True) - spinbox.setValue(vars(self._figure.subplotpars)[attr]) + spinbox.setValue(getattr(self._figure.subplotpars, attr)) spinbox.blockSignals(False) self._figure.canvas.draw_idle() diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 0915ba1c7b83..0008d2652ca8 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -324,11 +324,12 @@ def draw_if_interactive(): # show is already present, as the latter may be here for backcompat. manager_class = getattr(getattr(backend_mod, "FigureCanvas", None), "manager_class", None) - # We can't compare directly manager_class.pyplot_show and FMB.pyplot_show - # because pyplot_show is a classmethod so the above constructs are bound - # classmethods, & thus always different (being bound to different classes). - manager_pyplot_show = vars(manager_class).get("pyplot_show") - base_pyplot_show = vars(FigureManagerBase).get("pyplot_show") + # We can't compare directly manager_class.pyplot_show and FMB.pyplot_show because + # pyplot_show is a classmethod so the above constructs are bound classmethods, and + # thus always different (being bound to different classes). We also have to use + # getattr_static instead of vars as manager_class could have no __dict__. + manager_pyplot_show = inspect.getattr_static(manager_class, "pyplot_show", None) + base_pyplot_show = inspect.getattr_static(FigureManagerBase, "pyplot_show", None) if (show is None or (manager_pyplot_show is not None and manager_pyplot_show != base_pyplot_show)):