From e4c5f65bfd5d81929397e901df89dfc797d85ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Tue, 16 Jan 2024 13:54:56 +0100 Subject: [PATCH] plotters: Adjust to new renderer handling in Matplotlib 3.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The handling of the internal renderer objects changed in Matplotlib 3.6, and we haven't adjusted to the new API. Move the existing logic into a helper function so we can use it consistently, and try calling the new matplotlib API before falling back to the old logic. Fixes #291. Signed-off-by: Toke Høiland-Jørgensen --- flent/plotters.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/flent/plotters.py b/flent/plotters.py index 6adcaeca..235e9f15 100644 --- a/flent/plotters.py +++ b/flent/plotters.py @@ -952,6 +952,24 @@ def save_pdf(self, filename, data_filename, save_args): finally: pdf.close() + def _get_renderer(self): + + # Matplotlib 3.6 reorganised the renderer caching logic and introduced + # the _get_renderer() method of the figure class, so try that first + try: + return self.figure._get_renderer() + except AttributeError: + pass + + # Older versions of matplotlib cached the renderer in the figure itself, + # but it may not exist until after figure is drawn + renderer = getattr(self.figure, '_cachedRenderer', None) + if not renderer: + self.figure.canvas.draw() + renderer = getattr(self.figure, '_cachedRenderer', None) + + return renderer + def build_tight_layout(self, artists): args = None if self.fallback_layout: @@ -959,7 +977,7 @@ def build_tight_layout(self, artists): try: self.figure.savefig(io.BytesIO()) - renderer = self.figure._cachedRenderer + renderer = self._get_renderer() right = x_max = self.figure.get_figwidth() * self.figure.dpi top = y_max = self.figure.get_figheight() * self.figure.dpi vsp = 0.02 * self.figure.dpi @@ -1038,15 +1056,9 @@ def size_legends(self, event=None): and not self.legend_placement \ and self.legends: - # Make sure we have a renderer to get size from - renderer = getattr(self.figure, '_cachedRenderer', None) - if not renderer: - self.figure.canvas.draw() - renderer = getattr(self.figure, '_cachedRenderer', None) - try: legend_width = max( - [l.get_window_extent(renderer).width for l in self.legends]) + [l.get_window_extent(self._get_renderer()).width for l in self.legends]) except Exception as e: logger.debug("Error getting legend sizes: %s", e) return